Luet oppimateriaalin englanninkielistä versiota. Mainitsit kuitenkin taustakyselyssä osaavasi suomea. Siksi suosittelemme, että käytät suomenkielistä versiota, joka on testatumpi ja hieman laajempi ja muutenkin mukava.

Suomenkielinen materiaali kyllä esittelee englanninkielisetkin termit. Myös suomenkielisessä materiaalissa käytetään ohjelmaprojektien koodissa englanninkielisiä nimiä kurssin alkupään johdantoesimerkkejä lukuunottamatta.

Voit vaihtaa kieltä A+:n valikon yläreunassa olevasta painikkeesta. Tai tästä: Vaihda suomeksi.

# Chapter 6.2: Collections and Snakes

Questions Answered: How do higher-order methods make collections easy and pleasant to work with?

Topics: Methods on collections. We’ll also continue to use function literals a lot.

What Will I Do? Read and program.

Rough Estimate of Workload:? Three hours or more.

Points Available: B100.

Related Projects: Snake (new), Election.

## Introduction

This chapter will introduce you to a diverse set of higher-order methods that you can use instead of loops, or in combination with them. All of these methods have a couple of things in common: they are provided by the collection classes of the Scala API and they take in functions that specify what to do with the elements of the target collection. The methods respond to needs such as:

• How to repeat an operation on each element of a collection?
• How to examine a collection’s overall properties (e.g., whether all of its elements are similar to each other in some respect)?
• How to select some of a collection’s elements (e.g., all the elements that match a particular criterion)?
• How to combine elements to produce a result (e.g., the sum of squares of all elements, or a combination of all the pictures in a collection)?
• How to compute a separate result from each of a collection’s element (e.g., given a vector of person objects, produce a vector or their social security numbers)?

We expect that you’ll find the upcoming methods very convenient. You can use them to write code that is expressive and to-the-point. These methods are especially typical of functional programming (more on which in 10.2), whereas imperative programming tends to favor loops.

Much of this chapter consists of small examples of API methods. In that respect, we pick up where we left off in Chapter 4.1, which introduced a variety of (first-order) methods on collections.

For simplicity, many of the examples below feature integer vectors. However, the same methods work for collections other than vectors and elements other than numbers.

Many of the examples use function literals (Chapter 6.1) — both in the full form and abbreviated with underscores — so before you continue, please ensure that you understand those notations.

## Repeating an Operation with `foreach`

In a sense, the most generic of all the higher-order methods on Scala collections is `foreach`. As a first example, let’s use this method to print out the squares of each number in a collection.

```val numbers = Vector(10, 5, 4, 5, -20)numbers: Vector[Int] = Vector(10, 5, 4, 5, -20)
numbers.foreach( n => println(n * n) )100
25
16
25
400
```
`foreach` takes in a function that takes in a single element (here: an `Int`), such as the anonymous function that we have in this example.
As its name suggests, `foreach` performs the given operation on each element of the collection. In this case, it computes the square of each element and prints it out.
Note: even though the method name contains two English words, it is (against convention and somewhat confusingly) spelled with a lower-case `E`.

You probably noticed already that `foreach` does pretty much the same thing as `repeatForEachElement`, the higher-order function you wrote in Chapter 5.5. The main difference is that `foreach` is a library method available on all collections, and you can use it in any Scala program.

`foreach` expects to be given a function that returns `Unit`. Any function that we pass to `foreach` should therefore bring about an effect of some sort, such as printing (as above) or modifying an object’s state.

### Loops vs. methods on collections

As was already mentioned, the methods in this chapter can be used for similar purposes as loops. This is especially obvious in our first method, `foreach`. After all, you can also write:

```for (n <- numbers) {
println(n * n)
}
```

And indeed these two do the same thing:

```for (element <- elements) {
Do something with the element.
}
```
```elements.foreach( element => Do something with the element. )
```

As a matter of fact, a `for` loop such as the above is simply a different way of writing a `foreach` call. The Scala compiler automatically translates it into a method call.

As another example, here is one of the methods from Chapter 5.3’s `AuctionHouse` class:

```def nextDay() = {
for (current <- this.items) {
}
}
```

We could have just as well written:

```def nextDay() = {
}
```

Which one is more elegant and easier to read depends on context and on the programmer’s personal taste.

In O1, we’ll use `foreach` often, but we’ll continue to use the `for` loop as well. Feel free to use whichever you prefer, but an educated Scala programmer needs to be familiar with both.

## Examining a Collection

### Checking properties with `exists` and `forall`

The `exists` method is an easy way to determine whether or not any of the elements in the collection meets a particular criterion:

```val numbers = Vector(10, 5, 4, 5, -20)numbers: Vector[Int] = Vector(10, 5, 4, 5, -20)
numbers.exists( _ < 0 )res0: Boolean = true
numbers.exists( _ < -100 )res1: Boolean = false
```
We give `exists` a function that takes an element and returns a `Boolean` indicating whether the element meets a particular condition. Here, for instance, we pass in a function that determines whether its parameter is a negative number.
Our example collection contains (at least) one negative element. It doesn’t contain even a single element less than -100.

`forall` similarly checks whether all the elements of the collection fulfill the given criterion:

```numbers.forall( _ > 0 )res2: Boolean = false
numbers.forall( _ > -100 )res3: Boolean = true
```

In this example, we first checked whether all the elements are positive; they aren’t. Then we determined that all the elements are greater than -100.

### Getting to know `count`, `exists`, and `forall`

Use the REPL or other means to work out what the `count` method does. Try `numbers.count( _ % 2 == 0 )` and similar commands.

Which of the following claims are correct, assuming that `myCriterion` is the name of a function and `elements` is a variable that refers to a collection? (Also assume that `myCriterion`’s type is compatible with the collection.)

An afterthought

In the question above, why was one of the expressions written like this?

```// Version 1 (which works)
elements.forall( !myCriterion(_) )
```

Couldn’t we have simply written this?

```// Version 2 (which doesn't work)
elements.forall( !myCriterion )
```

As noted in Chapter 6.1, there are different ways to write a function literal. However, Version 2 doesn’t work, because it doesn’t actually define a function literal.

`forall`, like many other methods on collections, expects to be given a function that it can apply to each element in turn. However, the expression `!myCriterion` does not refer to any function, not even if there exists a function named `myCriterion`.

To pass in the reverse of `myCriterion`, you need to formulate a function that calls `myCriterion` and applies the negation operator `!` to the result. To that end, you can either use an underscore, as above, or the full arrow notation, as below.

```// Version 3 (which works)
elements.forall( elem => !myCriterion(elem) )
```

## Selecting Elements from a Collection

### Using `find`, `filter`, `takeWhile`, and `dropWhile`

The `find` method goes through the collection and returns the first element it finds that meets the given criterion. For instance, you could look for the first number that’s less than five:

```val numbers = Vector(10, 5, 4, 5, -20)numbers: Vector[Int] = Vector(10, 5, 4, 5, -20)
numbers.find( _ < 5 )res4: Option[Int] = Some(4)
```

Note: `find` returns an `Option` wrapped around the value that was found. If the search results in a miss, you get `None`:

```numbers.find( _ == 100 )res5: Option[Int] = None
```

`filter` is similar to `find` except that it returns a collection of all the elements that match the criterion. Our vector contains four positive numbers:

```val numbers = Vector(10, 5, 4, 5, -20)numbers: Vector[Int] = Vector(10, 5, 4, 5, -20)
numbers.filter( _ > 0 )res6: Vector[Int] = Vector(10, 5, 4, 5)
```

In Chapter 4.1, you saw a `take` method that returns a partial collection with the given number of elements from the beginning of the original collection (say, `numbers.take(3)`). `take`’s higher-order cousin is `takeWhile`:

```val numbers = Vector(10, 5, 4, 5, -20)numbers: Vector[Int] = Vector(10, 5, 4, 5, -20)
numbers.takeWhile( _ >= 5 )res7: Vector[Int] = Vector(10, 5)
```

As shown above, the method takes elements from the beginning of the collection until it runs into an element that doesn’t meet the given criterion.

### `filter` vs. `filterNot`; `takeWhile` vs. `dropWhile`

Use the REPL or other means to work out what the `filterNot` method does. You can invoke it just like `filter` above.

Assume that `elements` is a variable that refers to a vector. Further assume that we have `def`ined a function named `myCriterion` whose type is compatible with the collection. Which of the following claims are correct?

How about `dropWhile`? You can invoke it just like `takeWhile` above.

## Assignment: Reimplementing Election (Part 1 of 2)

This was a good activity. My code is so much shorter now.

In Chapter 5.4, you wrote a number of methods for class `District` in project Election. (If you didn’t, do that now or see the example solution.) At that time, you (probably) used loops to implement the methods.

Rewrite two of the methods, namely `printCandidates` and `candidatesFrom`. For each one, there exists a simple implementation that uses one of the methods introduced above. Use those methods instead of `for` loops.

We’ll get back to the other `District` methods later.

A+ presents the exercise submission form here.

## Mapping a Collection of Elements: `map` and `flatMap`

It is remarkably often useful to “map” a collection of elements to another.

The higher-order method `map` returns a new collection whose elements have been generated by applying `map`’s parameter function to each of original collection’s elements. In the example below, we use `map` to compute each element’s absolute value and obtain a new vector that contains each of the results in order:

```val numbers = Vector(10, 5, 4, 5, -20)numbers: Vector[Int] = Vector(10, 5, 4, 5, -20)
numbers.map( _.abs )res8: Vector[Int] = Vector(10, 5, 4, 5, 20)
```

The following expression determines, for each element, whether or not it is at least five. The output vector contains the resulting Booleans in order:

```numbers.map( _ >= 5 )res9: Vector[Boolean] = Vector(true, true, false, true, false)
```

You can use `map` in combination with a wide variety of parameter functions. Like the other methods of this chapter, `map` is also available on collections other than vectors. For instance, you can call it on the `Range` object that you get by writing `1 to 10` (Chapter 5.4):

```(1 to 10).map( n => n * n )res10: IndexedSeq[Int] = Vector(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
```

One more example, this time with strings as elements. Below, we call `map` to generate a new collection of integers that equal the lengths of the strings in the original collection.

```val animals = Vector("cat", "llama", "giraffe", "yak")animals: Vector[String] = Vector(cat, llama, giraffe, yak)
animals.map( _.length )res11: Vector[Int] = Vector(3, 5, 7, 3)
```

Observe: in general terms, what we did above is take in a collection of objects (here: strings) and pick out a specific property of each object (here: length). This is a common pattern; you’ll see a more interesting example of it later in this chapter.

### Getting to know `map`

Suppose we have a variable of type `Vector[Double]` with the name `numbers`. Use `map` to write a Scala expression that computes the numbers’ square roots. That is, the expression’s value must be a reference to a new vector that contains the square roots of each element in `numbers` in order. You may assume that the command `import scala.math.sqrt` has been already given.

Suppose you have a variable `buffer` of type `Buffer[Int]` that refers to a “one-dimensional” buffer of numbers. Let’s also assume the buffer contains a minimum of one element.

What happens if you now evaluate `buffer.map( x => Buffer(x, x + 1) )`? Experiment in the REPL as needed.

`map` vs. `transform`

The `transform` method is a relative of `map` that is available only on mutable collections such as buffers (but not on, say, vectors). Whereas `map` returns a new collection, `transform` replaces each element of the original collection with another. `transform` therefore closely resembles the `transformEachElement` function you wrote in Chapter 5.5.

Incidentally, the `transformColors` method of Chapter 5.5 is also a close relative of `map`: it maps colors to other colors.

### The `flatMap` method

Chapter 5.5 mentioned a method that “flattens” a collection of collections:

```val nested = Vector(Vector(3, -10, -4), Vector(5, -10, 1), Vector(-1), Vector(4, 4))nested: Vector[Vector[Int]] = Vector(Vector(3, -10, -4), Vector(5, -10, 1), Vector(-1), Vector(4, 4))
nested.flattenres12: Vector[Int] = Vector(3, -10, -4, 5, -10, 1, -1, 4, 4)
```

It’s fairly common that we want to first `map` a collection to produce a nested collection, then `flatten` the result. Here’s a toy example:

```val numbers = Vector(10, 5, 4, 5, -20)numbers: Vector[Int] = Vector(10, 5, 4, 5, -20)
val experiment = numbers.map( n => Vector(-n.abs, 0, n.abs) )experiment: Vector[Vector[Int]] = Vector(Vector(-10, 0, 10), Vector(-5, 0, 5), Vector(-4, 0, 4), Vector(-5, 0, 5),
Vector(-20, 0, 20))
experiment.flattenres13: Vector[Int] = Vector(-10, 0, 10, -5, 0, 5, -4, 0, 4, -5, 0, 5, -20, 0, 20)
```

It’s possible to combine `map` and `flatten` into a single method call:

```numbers.flatMap( n => Vector(-n.abs, 0, n.abs) )res14: Vector[Int] = Vector(-10, 0, 10, -5, 0, 5, -4, 0, 4, -5, 0, 5, -20, 0, 20)
```

That is, `collection.flatMap(myFunc)` does the same as `collection.map(myFunc).flatten`.

You may well be wondering whether combining `map` with `flatten` is so useful that it merits a separate `flatMap` method. Yes, it really is. You’ll see as your programming experience grows during the rest of O1 and later.

For a somewhat more interesting example of `map` and `flatMap`, consider the following class.

```class User(val id: String, val emailAddresses: Vector[String]) {
override def toString = this.id + " <" + this.emailAddresses.mkString(",") + ">"
}
```

Let’s imagine we’re working on an application that stores `User` objects in a vector. In the example below, our vector contains just two users, but of course there could be many more.

```val allUsers = Vector(
new User("sophia", Vector("sophia.student@aalto.fi", "sophia.student@iki.fi", "sophia.student@gmail.com")),
)allUsers: Vector[User] =
Vector(sophia <sophia.student@aalto.fi,sophia.student@iki.fi,sophia.student@gmail.com>,
```

How can we now get a list of all the `id`s of all the users? What about a list of all the email addresses of all the users?

Sure, we could write a loop, but the just-introduced methods get the job done with minimal effort.

The `map` method gives us each user’s identifier if we pass in a function that maps a user object to its `id`.

```allUsers.map( _.id )res15: Vector[String] = Vector(sophia, megadestroyer)
```

We can also use `map` to access the email addresses. This gives us a nested collection (which, depending on our purposes, may or may not be convenient):

```allUsers.map( _.emailAddresses )res16: Vector[Vector[String]] = Vector(Vector(sophia.student@aalto.fi, sophia.student@iki.fi, sophia.student@gmail.com),
Vector(teemu.teekkari@aalto.fi, teemuteekkari@gmail.com))
```

Assuming we want a single “flat” collection of all the emails, we can use `flatMap` instead:

```allUsers.flatMap( _.emailAddresses )res17: Vector[String] = Vector(sophia.student@aalto.fi, sophia.student@iki.fi, sophia.student@gmail.com,
teemu.teekkari@aalto.fi, teemuteekkari@gmail.com)
```

The next programming assignment is not only about methods on collections, but it does provide opportunities to use them.

## Assignment: Snake

Snake is a classic computer game that originates from the 1970s: the player controls a “snake” or “worm” that turns about on a two-dimensional field, looking to eat and grow. In the 1990s, Snake renewed its popularity as a mobile game, which has in turn recently attracted nostalgic attention. By the time you read this, the game may have already reverted to passé retro kitch.

A game of Snake with an overlying grid for illustrative purposes. The green square represents an item of food that the snake can eat next; the food is at location (8,6). The numbering starts at the top left-hand corner, which is (0,0); that space, like the other edge spaces, are only partially visible. The snake in this picture has four segments, which are located at (5,4), (4,4), (3,4), and (3,5).

Snake is also a classic as a programming exercise. Let us join the tradition.

### The concepts of Snake

The key components of a game of Snake are the snake itself and the food that the snake seeks to swallow. At any given moment, there is a single item of food available for the snake, located somewhere on the playing field. When the snake eats the food — that is, when the snake’s head is about to hit it — the snake grows and a new item of food appears.

You can think of the playing field as a grid (see image). The food is located in a single space on the grid. The snake consists of segments (“pieces”), each of which takes up a space.

In the picture above, the snake had traveled upwards and then turned to the right. In this picture, the snake has moved a single additional step compared to the previous state. The snake’s head has moved a single step to the right and “dragged” the other three segments with it. The location (3,5), which previously contained the last segment, is now empty.

The only thing the player can do is press one of the arrow keys to make the snake turn in that direction. The snake can move only in the four main compass directions.

As time passes, the snake moves step by step: its first segment, or “head”, moves in the latest direction chosen by the player and the other segments follow (see the second image). However, if the head enters the food space, the snake eats the food and grows by a single segment: a new segment appears where the food was and all the other segments remain where they were.

The game is over when the snake’s head hits something other than food.

### The classes in project `Snake`

The project Snake contains a partial implementation for the game. The overall design of the program resembles that of FlappyBug: we have a `SnakeGame` class that represents the mutable state of a game and a `SnakeApp` object that starts a GUI for displaying the state and receiving commands from the player.

So, an instance of `SnakeGame` represents a single session of Snake. Calling that instance’s methods changes its state. The `SnakeGame` object tracks:

• the next item of food: where is it on the grid?
• the location of the snake: where on the grid are its segments?
• the direction of the (head of the) snake: which of the four compass directions has it been ordered to go?

Our class needs to manipulate locations on the grid as well as directions. For that, we have tools on hand in package `o1`:

### The classes `GridPos` and `CompassDir`

Class `GridPos` represents coordinates on a grid. Each coordinate is an integer.

• This class resembles the `Pos` you know but is specifically designed for use with grids and provides some convenient methods to that end.
• We therefore distinguish between two things: which space something is located at (`GridPos`) and which spot within a particular image something should be drawn at (`Pos`).
• The `GridPos` is part of the program domain’s internal logic (i.e., the rules of Snake). The `Pos` is a feature of the GUI.
• This is similar to what we did in the Stars project, where we distinguished between a `StarCoords` on a map and a `Pos` within an image.

The class `CompassDir` represents compass directions such as north (up) and west (left):

• It’s well suited for representing the snake’s heading.
• It combines well with the methods on `GridPos`. For instance, we can ask a `GridPos` object which coordinates neighbor it in a particular direction.

Both classes are documented within the O1Library project.

Relationships between classes in and around the Snake project.

In `SnakeGame.scala` and `SnakeApp.scala`, find the locations where something is missing and implement the missing parts. We suggest that you proceed as follows.

### Step 0 of 4: preparations

Run the given program. You should see a playing field with a food item and a single-segment snakeling. (There is no visible grid like in the illustrations above; that’s intentional.) The snake doesn’t move yet.

Study class `SnakeGame` and its companion object. Observe that there are parts missing. Note how the given code uses the classes `GridPos` and `CompassDir`. In the Scaladocs for those other classes, read at least the introductions at the top; there’s no need to wade through all the methods. (The Snake project itself has no Scaladocs. All the information you need is in this chapter and in the Scala code.)

You may want to take a look at `SnakeApp`, too.

As the clock ticks, the GUI calls the `advance` method of the appropriate `SnakeGame` object. `advance` is supposed to move the snake. The given version doesn’t do anything, however.

### Step 1 of 4: a mobile snake

For now, write a partial implementation for `advance`: make it move the snake’s head to the next space. Don’t worry about growing the snake yet.

Hints:

• The `segments` variable refers to a single-element vector that contains the location of the (head of the) snake. This is a `var`: replace its value with the neighboring location towards the current heading.
• There is a convenient method in `GridPos` for that.

Run the modified program. See the single segment slither.

The game ends when the snake hits an edge. You control the snake with the arrow keys (or WASD). The snake ignores the food.

### Step 2 of 4: snacks for snakes

Develop `advance` further so that it places the food in a new random location as part of the movement that puts the snake’s only segment enters in the food space.

You can do that by updating the value of the `nextFood` variable. Use the given method `randomLocationOnGrid` to pick a new location.

Then finish up `advance`: 1) when the head is just about to hit the food, grow the snake, and 2) when the snake doesn’t eat, move each segment rather than just the head. Here are some hints:

• Replace the value of `segments` with a new vector that contains the updated locations of each segment. After a move, there should be as many segments as before, or one more.
• When the snake’s head is about to hit food, grow the snake from the front: all the other segments stay where they are and a new head segment appears. (The frontmost segment becomes the second-from-front.)
• You can use the tools from 4.1 to form the new vector. In particular, you may want to use the `+:` operator, which “adds” an element to the front like this:
• `newFirstElement +: oldVector`
• The segments are identical. You don’t have to move each segment separately. When the snake moves, you can leave the middle segments where they are: taking care of the first and last segments is enough for the appearance of movement.
• There’s a `GameSpeed` constant in `SnakeApp`. You can adjust it to your liking. You might want to slow down the game while testing, for instance.

Try running your program. Food gets eaten, but the snake doesn’t seem to grow.

It does in fact grow, but you don’t see it because the GUI draws only the head.

### Step 3 of 4: sorting out the graphics

Turn to the `SnakeApp` program and the `makePic` method defined there. Observe:

• The method places only a single copy of `SegmentPic` (reddish picture of a snake segment) against the background.
• `makePic` uses an auxiliary function `toPixelPos`, which is defined in the same file. That function takes in a `GridPos` and determines where in the GUI image that space should be drawn.
• `makePic` also uses a `placeCopies` method from class `Pic`. As its first parameter, that method takes a picture. As its second parameter, it takes a vector of `Pos` objects. That method works just like the familiar `place` method, except that it places multiple copies of the same image. Which doesn’t help much yet, since the given code passes in only a single-element vector.

Edit `makePic` so that it draws all the segments as identical round shapes. Here’s how:

• Use `toPixelPos` to determine each segment’s position within the image. You don’t need a loop. Use one of the collection methods from this chapter.
• Call `placeCopies`, passing in a vector that contains a `Pos` for each segment.

The snake grows!

### Step 4 of 4: collisions

It is ordained by the tradition of snake gaming that snakes die if they collides with their own body. Attend to this in class `SnakeGame`: the `isOver` method should indicate that the game is over not only when the snake hits a wall but also if its head shares a location with any of the other segments.

You can again turn to Chapter 4.1 for tooling.

### Submission form

A+ presents the exercise submission form here.

Higher-order methods and Scala syntax

Reading Scala programs outside O1, you’ll fairly soon run into programs that use the methods from this chapter in a different-looking way than we have. This command, for example:

```myNumbers.filter( _ > 0 ).map( n => n * n ).count( _ % 2 == 0 )
```

can also be written as:

```myNumbers filter { _ > 0 } map { n => n * n } count { _ % 2 == 0 }
```

Scala’s syntax is flexible and people use the language in different ways. The latter notation is made possible by two language features:

• You can use operator notation instead of dot notation to call a method. Some Scala programmers tend to do this whenever they call an effect-free higher-order method that takes a single parameter.
• When calling a method that takes a single parameter, you can use curly brackets instead of round brackets. Some Scala programmers tend to do this when they pass a function literal as a parameter to a method.

Even if you don’t use these alternative notations, it’s good to know about them since some others do use them.

As noted in Chapter 4.5, we largely avoid operator notation in O1.

## Summary of Key Points

• The collection classes of the Scala API define a whole bunch of higher-order methods that operate on the elements of collections.
• Methods in common use include `foreach`, `exists`, `forall`, `find`, `filter`, `map`, and `flatMap`. You’ll see more later.
• These methods provide generic solutions to common problems and are often a convenient alternative to loops.
• Processing collections in this manner is especially common in so-called functional programming, which Scala encourages.
• Links to the glossary: higher-order function; collection; level of abstraction.

Why This Chapter Matters

We’ll make frequent use of the methods introduced above. They will serve you well in upcoming programming assignments.

You’ll need to read a lot of given code that uses these methods.

You may initially struggle to recall each method. Then again, you don’t need to. You can return to this chapter for reference, or use our Scala Reference.

The important thing for now is to bear in mind the general idea: there is a wide selection of convenient higher-order methods on offer.

## Feedback

Please note that this section must be completed individually. Even if you worked on this chapter with a pair, each of you should submit the form separately.

## Credits

Thousands of students have given feedback that has contributed to this ebook’s design. Thank you!

Weeks 1 to 13 of the ebook, including the assignments and weekly bulletins, have been written in Finnish and translated into English by Juha Sorva.

Weeks 14 to 20 are by Otto Seppälä. That part of the ebook isn’t available during the fall term, but we’ll publish it when it’s time.

The appendices (glossary, Scala reference, FAQ, etc.) are by Juha Sorva unless otherwise specified on the page.

The automatic assessment of the assignments has been programmed by Riku Autio, Jaakko Kantojärvi, Teemu Lehtinen, Timi Seppälä, Teemu Sirkiä, and Aleksi Vartiainen.

The illustrations at the top of each chapter, and the similar drawings elsewhere in the ebook, are the work of Christina Lassheikki.

The animations that detail the execution Scala programs have been designed by Juha Sorva and Teemu Sirkiä. Teemu Sirkiä and Riku Autio have done the technical implementation, relying on Teemu’s Jsvee and Kelmu toolkits.

The other diagrams and interactive presentations in the ebook are by Juha Sorva.

The O1Library software has been developed by Aleksi Lukkarinen and Juha Sorva. Several of its key components are built upon Aleksi’s SMCL library.

The pedagogy of using tools from O1Library (such as `Pic`) for simple graphical programming is inspired by the textbooks How to Design Programs by Flatt, Felleisen, Findler, and Krishnamurthi and Picturing Programs by Stephen Bloch.

The course platform A+ has been created by Aalto’s LeTech research group and is largely developed by students. The current lead developer is Jaakko Kantojärvi; many other students of computer science and information networks are also active on the project.

For O1’s current teaching staff, please see Chapter 1.1.

Additional credits appear at the ends of some chapters.

Posting submission...