Let’s start with a simple iteration: given a list of stock prices, we’d like to print each price on a separate line.
Initially, the traditional for loop comes to mind, something like this in Java:
| for(int i = 0; i <= prices.size(); i++) |
Or is it < instead of <= in the loop condition?
There is no reason to burden ourselves with that. We can just use the for-each construct in Java, like so:
| for(double price : prices) |
Let’s follow this style in Scala:
| val prices = List(211.10, 310.12, 510.45, 645.60, 832.33) |
| for(price <- prices) { |
| println(price) |
| } |
Scala’s type inference determines the type of the prices list to be List[Double] and the type of price to be Double. The previous style of iteration is often referred to as an external iterator. Scala also supports internal iteration, so we could write the previous example using the foreach function of List.
| prices.foreach { e => println(e) } |
The foreach function is our first example of a higher-order function: it receives another function as a parameter.
Let’s reflect on this code for a moment. In general, a function has four parts: name, parameter list, return type, and body. Of these four, the body is the most important. In the previous function that’s passed to foreach, the body is between the => and the closing }. The parameter list has one parameter e and since Scala can infer type, we did not have to say e : Double, though we could. Scala already knows the return type of this function based on what foreach expects and this function is anonymous, so does not have any name. The anonymous function we passed previously is called a function value in Scala.
But Scala has the smarts to allow us to reduce the code even further. If we simply pass the parameter received in the function value to another function in the body, as in this example, we can let Scala do that job:
| prices.foreach { println } |
That reduced some noise in the code; the parameter was received in the function value and passed to println.
We can take this up another notch: Scala makes quite a few things optional, including dot, so we can refactor the previous code to
| prices foreach println |
Here we’re sending the println function itself as a parameter to the foreach method instead of wrapping a call to it into a function value—the println function itself is treated here as a function value.
All right, we know how to use the functional style to iterate over elements: simply pass a function value that operates on an element to the internal iterator and it takes care of calling that function value with each element in the list as a parameter. And this can clearly produce some concise code.
We can explore this further. There are different flavors of internal iterators available on collections in Scala. Let’s look at the benefits a few of these offer.
If we want to pick the first price that’s greater than $500, we can do that without mutating any variables (functional purity):
| prices find { price => price > 500 } |
If we want all the prices that are greater than $500, we just replace find with the filter function.
| prices filter { price => price > 500 } |
If we have to compute ten percent of each of the prices given, we can achieve this elegantly using the map function.
| println(prices map { price => price * 0.1 }) |
will print
| List(21.11, 31.012, 51.045, 64.56, 83.233) |
The map function applies the function value given, once for each element in the list, collects the result from the function value (which is ten percent of the price in this example) into a list, and returns the collected list.
Finally, say we’re asked to total the prices given. We’re quite familiar with how to do that in the imperative style.
| var total = 0.0 |
| for(price <- prices) { |
| total += price |
| } |
| |
| println("Total is " + total) |
to get the output of
| Total is 2509.6 |
However, a variable was tortured in the making of this example. We can avoid that with functional style again.
| println("Total is " + prices.reduce { (price1, price2) => price1 + price2 }) |
| //Total is 2509.6 |
The reduce function takes a function value that accepts two values. In the first call to the function value, price1 is bound to the first element in the list and price2 is bound to the second element. In each of the subsequent calls to the function value, price1 is bound to the result of the previous call to this function value and price2 to the subsequent elements in the list. The reduce function returns the result from the last call to the function value once it has been applied for each of the elements in the list.
Scala also provides a specialized version of the reduce function specifically to sum up values—the sum function. Here’s how we can use it for the preceding example:
| println("Total is " + prices.sum) |
We’ve seen a few functions here that are typical of functional style: foreach, find, filter, map, and reduce. It’s time to put these to a practical use.