Skip to content

Latest commit

 

History

History
203 lines (134 loc) · 5.54 KB

anonymous-functions.md

File metadata and controls

203 lines (134 loc) · 5.54 KB
typelayouttitledescriptionpartofoverview-namenumoutofprevious-pagenext-pagenew-version
section
multipage-overview
Anonymous Functions
This page shows how to use anonymous functions in Scala, including examples with the List class 'map' and 'filter' functions.
scala_book
Scala Book
34
54
set-class
collections-methods
/scala3/book/fun-anonymous-functions.html

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

valints=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:

valints=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>valints=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:

valints=List(1,2,3)

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

valdoubledInts= ints.map(_ *2)

This is what that example looks like in the REPL:

scala>valdoubledInts= 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:

valdoubledInts= ints.map(_ *2)

you can also write it like this:

valdoubledInts= ints.map((i: Int) => i *2) valdoubledInts= 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 = newArrayList<>(Arrays.asList(1, 2, 3)); // the `map` processList<Integer> doubledInts = ints.stream() .map(i -> i * 2) .collect(Collectors.toList());

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

valdoubledInts=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:

valints=List.range(1, 10)

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

valx= ints.filter(_ >5)

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

valx= 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:

valx= ints.filter(_ %2==0)

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

valx= ints.filter((i: Int) => i %2==0) valx= ints.filter(i => i %2==0)

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

scala>valx= ints.filter(_ >5) x:List[Int] =List(6, 7, 8, 9) scala>valx= ints.filter(_ <5) x:List[Int] =List(1, 2, 3, 4) scala>valx= 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:

valints=List(1,2,3) defdouble(i: Int):Int= i *2//a method that doubles an IntvaldoubledInts= ints.map(double)

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

valdoubledInts= 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:

deflessThanFive(i: Int):Boolean=if (i <5) trueelsefalse

or more concisely, like this:

deflessThanFive(i: Int):Boolean= (i <5)

this filter example:

valints=List.range(1, 10) valy= ints.filter(lessThanFive)

is the same as this example:

valy= ints.filter(_ <5)
close