We have seen how to define functions and methods using the def keyword. Such a method is compiled to some code with the given name.
In Scala, it is also possible to create function objects without giving it a name. A function object is an object that can be used like a function (that is, it has an apply method).
Here is a simple example:
scala> (x: Int) => x + 1 res1: (Int) => Int = <function1>Here we have created a function object that takes one Int argument and returns the argument plus one. The type of the object is (Int) => Int. A function object can be used like a function:
scala> val f = (x: Int) => x + 1 f: (Int) => Int = <function1> scala> f(3) res1: Int = 4 scala> f(7) res2: Int = 8 scala> f(9) res3: Int = 10
We can make this even more interesting. In the following function object g, the function definition makes use of a variable more:
scala> var more = 5 more: Int = 5 scala> val g = (x: Int) => x + more g: (Int) => Int = <function1> scala> g(4) res1: Int = 9 scala> g(10) res2: Int = 15
But what happens if we change the value of more? The answer is that the behavior of the function object changes as well:
scala> more = 10 more: Int = 10 scala> g(4) res3: Int = 14 scala> g(10) res4: Int = 20We say that the variable more is a free variable of the function object. The behavior of a function object depends not only on its arguments, but also on its free variables.
When working with collections, there are many common functions that can be implemented as a for-loop:
scala> for (e <- C) | println(e) Otfried Jungwoo Youngwoon
Higher-order methods allow us to concentrate on the interesting part of this loop, namely the print statement:
scala> C.foreach((x: String) => println(x)) Otfried Jungwoo YoungwoonThe foreach method is called a higher-order method because its argument is itself a function object. In a sense, foreach is a "meta-function" that works on other functions.
The code above can be simplified, because the Scala compiler knows that the argument of foreach has to be a function object. Therefore we are allowed to omit the type of the argument:
scala> C.foreach((x) => println(x)) Otfried Jungwoo YoungwoonIn this case, there is only one argument, and so we are even allowed to remove the parentheses:
scala> C.foreach(x => println(x)) Otfried Jungwoo YoungwoonAs a final simplification, when the function object has only a single argument and this argument is only used once in the result expression, we can omit the x => part completely and replace the parameter by an underscore:
scala> C.foreach(println(_)) Otfried Jungwoo Youngwoon