Differences between these three ways of defining a function in Scala
Given three ways of expressing the same function f(a) := a + 1
:
val f1 = (a:Int) => a + 1
def f2 = (a:Int) => a + 1
def f3:(Int => Int) = a => a + 1
How do these definitions differ? The REPL does not indicate any obvious differences:
scala> f1
res38: (Int) => Int = <function1>
scala> f2
res39: (Int) => Int = <function1>
scala> f3
res40: (Int) => Int = <function1>
Solution 1:
Inside a class, val
is evaluated on initialization while def
is evaluated only when, and every time, the function is called. In the code below you will see that x is evaluated the first time the object is used, but not again when the x member is accessed. In contrast, y is not evaluated when the object is instantiated, but is evaluated every time the member is accessed.
class A(a: Int) {
val x = { println("x is set to something"); a }
def y = { println("y is set to something"); a }
}
// Prints: x is set to something
val a = new A(1)
// Prints: "1"
println(a.x)
// Prints: "1"
println(a.x)
// Prints: "y is set to something" and "1"
println(a.y)
// Prints: "y is set to something" and "1"
println(a.y)
Solution 2:
f1
is a function that takes an integer and returns an integer.
f2
is a method with zero arity that returns a function that takes an integer and returns an integer. (When you type f2
at REPL later, it becomes a call to the method f2
.)
f3
is same as f2
. You're just not employing type inference there.
Solution 3:
Executing a definition such as def x = e will not evaluate the expression e. Instead e is evaluated whenever x is used. Alternatively, Scala offers a value definition val x = e, which does evaluate the right-hand-side e as part of the evaluation of the definition. If x is then used subsequently, it is immediately replaced by the pre-computed value of e, so that the expression need not be evaluated again.
Scala By Example by Martin Odersky