# Transforming Sequences

In imperative programs we use loops to iterate over lists and transform them to produce new values. For example, here is a Java 7 method to double the numbers in an `ArrayList`:

``````List<Integer> doubleAll(List<Integer> numbers) {
List<Integer> ans = new ArrayList<Integer>();

for(int i : numbers) {
ans.push(i * 2);
}

return ans;
}

List<Integer> result = doubleAll(new ArrayList<Integer>(1, 2, 3, 4, 5));``````

There are a lot of lines in this example, many of which aren't to do with the desired operation of doubling numbers. We have to allocate a temporary list and push numbers onto it before returning it, all of which ought to be be handled by library code.

We can't easily abstract away the temporary list allocation in Java 7 because we have no direct way of abstracting the doubling operation. In Scala and Java 8 we can represent doubling succinctly using a function literal, aka a "closure":

``````(x: Int) => x * 2
// res2: Int => Int = <function1>

res2(10)
// res3: Int = 20``````

Scala's `List` class has a method called `map` that allows us to exploit functions to remove all of the boilerplate from our Java 7 example. `map` accepts a function as a parameter and returns a new `List` created by applying the function to every item:

``````List(1, 2, 3, 4, 5).map(i => i * 2)
// res4: List[Int] = List(2, 4, 6, 8, 10)``````

We can use the `map` method to convert `Lists` of values to `Lists` of `Images`:

``````val radii = List(10, 20, 30, 40, 50)
// radii: List[Int] = List(10, 20, 30, 40, 50)

val circles = radii.map(i => Circle(i * 10))
// circles: List[doodle.core.Circle] = // ...``````

Doodle contains a handful of convenient methods to convert values of type `List[Image]` to single `Images`. One of these is `allBeside`, which lays a list of images out beside one another:

``allBeside(circles).draw`` Other combinators are listed below:

Operator Type Description Example ------------------------- ------- -------------------------- ----------------------------------- `allBeside(listOfImages)` `Image` Places images horizontally `allBeside(Circle(10), Circle(20))` next to one another.

`allAbove(listOfImages)` `Image` Places images vertically `allAbove(Circle(10), Circle(20))` above one another.

`allBelow(listOfImages)` `Image` Places images vertically `allBelow(Circle(10), Circle(20))` below one another.

`allOn(listOfImages)` `Image` Places images centered `allOn(Circle(10), Circle(20))` on top of one another.

`allUnder(listOfImages)` `Image` Places images centered `allUnder(Circle(10), Circle(20))` underneath one another. -----------------------------------------------------------------------------------------------

We can recreate our concentric circles example trivially using `allOn` or `allUnder`. Much simpler than writing a recursive method!

``````val radii = List(10, 20, 30, 40, 50)
// radii: List[Int] = List(10, 20, 30, 40, 50)

val circles = radii.map(i => Circle(i))
// circles: List[Circle] = // ...

allOn(circles).draw``````

Exercise: Colour Palette

Create an application to show the range of colours you can get in HSL space. Create a two-dimensional grid of rectangles, with hue varying from 0 to 360 degrees on the x-axis and lightness varying from 0.0 to 1.0 on the y-axis. Here are some tips:

1. Think about the structure of your image and build it from the bottom up. Start by building a single square of constant hue and lightness, then compose a sequence of squares into a single column, then compose a sequence of columns together to form the palette.
1. You can create an HSL colour as follows:

``````val hue = 180.degrees

val lightness = 0.5.normalized

val color = Color.hsl(hue, 1.0.normalized, lightness)``````

For extra credit, allow the user to specify parameters for the step size along each axis and the basic shape used in each cell: <div class="solution"> First let's define a method to create a single square. We'll call the method `cell` to keep the naming shape-independent and specify `size`, `hue`, and `lightness` as parameters:

``````def cell(size: Int, hue: Int, lightness: Double): Image =
Rectangle(size, size) strokeWidth 0 fillColor Color.hsl(hue.degrees, 1.0.normalized, lightness.normalized)``````

Next let's create a single column of varying lightness. We start with a list of lightness values, map over the list to produce the squares, and build the column using `allAbove` or `allBelow`:

``````def column(cellSize: Int, hue: Int): Image = {
val cells =
(0.0 until 1.0 by 0.01).toList map { lightness =>
cell(cellSize, hue, lightness)
}

allAbove(cells)
}``````

Finally let's assemble the columns into a palette. We start with a list of hues, map over it to create columns, and build the palette using `allBeside`:

``````def palette(cellSize: Int): Image = {
val columns =
(0 until 360 by 2).toList map { hue =>
column(cellSize, hue)
}

allBeside(columns)
}``````

For the extra credit solution we add `hStep`, `lStep`, and `cell` parameters. `hStep` and `lStep` are of type `Int` and `Double` respectively, and `cell` is of type `(Int, Double) => Image`. In the example below we use a type alias to make the type of the `cell` parameter more explicit. Type aliases are simply a way of naming types---the compiler treats an aliased type exactly the same as an unaliased one:

``````// Type alias for cell constructor functions:

type CellFunc = (Int, Double) => Image

// Different types of cell:

def squareCell(size: Int): CellFunc =
(hue: Int, lightness: Double) =>
Rectangle(size, size) strokeWidth 0 fillColor Color.hsl(hue.degrees, 1.0.normalized, lightness.normalized)

def circleCell(size: Int): CellFunc =
(hue: Int, lightness: Double) =>
Circle(size/2) strokeWidth 0 fillColor Color.hsl(hue.degrees, 1.0.normalized, lightness.normalized)

// Code to construct a palette:

def column(hue: Int, lStep: Double, cell: CellFunc): Image = {
val cells =
(0.0 until 1.0 by lStep).toList map { lightness =>
cell(hue, lightness)
}

allAbove(cells)
}

def palette(hStep: Int, lStep: Double, cell: CellFunc): Image = {
val columns =
(0 until 360 by hStep).toList map { hue =>
column(hue, lStep, cell)
}

allBeside(columns)
}

// Example use of the palette() method:

palette(2, 0.01, circleCell(10))``````

</div>

There are many other methods in the Scala standard library for transforming sequences using functions as parameters. We won't cover them in this course, but here is a sample of a few really useful ones:

Start with Method Parameter Result Description ---------- --------- -------------- ----------- ---------------------------------- `List[A]` `map` `A => B` `List[B]` Return all elements, transformed by the function.

`List[A]` `filter` `A => Boolean` `List[A]` Return all elements for which the function returns `true`.

`List[A]` `flatMap` `A => List[B]` `List[B]` Return all elements, transformed by the function and concatenated into a single `List`.

`List[A]` `find` `A => Boolean` `Option[B]` Return the first element for which the function returns `true`. ----------------------------------------------------------------------------------

Drawing Paths→