Scala Book

# Anonymous Functions

Language

Earlier in this book you saw that you can create a list of integers like this:

``````val ints = List(1,2,3)
``````

When you want to create a larger list, you can also create them with the `List` class `range` method, like this:

``````val ints = List.range(1, 10)
``````

That code creates `ints` as a list of integers whose values range from 1 to 10. You can see the result in the REPL:

``````scala> val ints = List.range(1, 10)
x: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
``````

In this lesson we’ll use lists like these to demonstrate a feature of functional programming known as anonymous functions. It will help to understand how these work before we demonstrate the most common Scala collections methods.

## Examples

An anonymous function is like a little mini-function. For example, given a list like this:

``````val ints = List(1,2,3)
``````

You can create a new list by doubling each element in `ints`, like this:

``````val doubledInts = ints.map(_ * 2)
``````

This is what that example looks like in the REPL:

``````scala> val doubledInts = ints.map(_ * 2)
doubledInts: List[Int] = List(2, 4, 6)
``````

As that shows, `doubledInts` is now the list, `List(2, 4, 6)`. In this example, this code is an anonymous function:

``````_ * 2
``````

This is a shorthand way of saying, “Multiply an element by 2.”

Once you’re comfortable with Scala, this is a common way to write anonymous functions, but if you prefer, you can also write them using longer forms. Besides writing that code like this:

``````val doubledInts = ints.map(_ * 2)
``````

you can also write it like this:

``````val doubledInts = ints.map((i: Int) => i * 2)
val doubledInts = ints.map(i => i * 2)
``````

All three lines have exactly the same meaning: Double each element in `ints` to create a new list, `doubledInts`.

The `_` character in Scala is something of a wildcard character. You’ll see it used in several different places. In this case it’s a shorthand way of saying, “An element from the list, `ints`.”

Before going any further, it’s worth mentioning that this `map` example is the equivalent of this Java code:

``````List<Integer> ints = new ArrayList<>(Arrays.asList(1, 2, 3));

// the `map` process
List<Integer> doubledInts = ints.stream()
.map(i -> i * 2)
.collect(Collectors.toList());
``````

The `map` example shown is also the same as this Scala code:

``````val doubledInts = for (i <- ints) yield i * 2
``````

## Anonymous functions with the `filter` method

Another good way to show anonymous functions is with the `filter` method of the `List` class. Given this `List` again:

``````val ints = List.range(1, 10)
``````

This is how you create a new list of all integers whose value is greater than 5:

``````val x = ints.filter(_ > 5)
``````

This is how you create a new list whose values are all less than 5:

``````val x = ints.filter(_ < 5)
``````

And as a little more complicated example, this is how you create a new list that contains only even values, by using the modulus operator:

``````val x = ints.filter(_ % 2 == 0)
``````

If that’s a little confusing, remember that this example can also be written in these other ways:

``````val x = ints.filter((i: Int) => i % 2 == 0)
val x = ints.filter(i => i % 2 == 0)
``````

This is what the previous examples look like in the REPL:

``````scala> val x = ints.filter(_ > 5)
x: List[Int] = List(6, 7, 8, 9)

scala> val x = ints.filter(_ < 5)
x: List[Int] = List(1, 2, 3, 4)

scala> val x = ints.filter(_ % 2 == 0)
x: List[Int] = List(2, 4, 6, 8)
``````

## Key points

The key points of this lesson are:

• You can write anonymous functions as little snippets of code
• You can use them with methods on the `List` class like `map` and `filter`
• With these little snippets of code and powerful methods like those, you can create a lot of functionality with very little code

The Scala collections classes contain many methods like `map` and `filter`, and they’re a powerful way to create very expressive code.

## Bonus: Digging a little deeper

You may be wondering how the `map` and `filter` examples work. The short answer is that when `map` is invoked on a list of integers — a `List[Int]` to be more precise — `map` expects to receive a function that transforms one `Int` value into another `Int` value. Because `map` expects a function (or method) that transforms one `Int` to another `Int`, this approach also works:

``````val ints = List(1,2,3)
def double(i: Int): Int = i * 2   //a method that doubles an Int
val doubledInts = ints.map(double)
``````

The last two lines of that example are the same as this:

``````val doubledInts = ints.map(_ * 2)
``````

Similarly, when called on a `List[Int]`, the `filter` method expects to receive a function that takes an `Int` and returns a `Boolean` value. Therefore, given a method that’s defined like this:

``````def lessThanFive(i: Int): Boolean = if (i < 5) true else false
``````

or more concisely, like this:

``````def lessThanFive(i: Int): Boolean = (i < 5)
``````

this `filter` example:

``````val ints = List.range(1, 10)
val y = ints.filter(lessThanFive)
``````

is the same as this example:

``````val y = ints.filter(_ < 5)
``````