在 Scala 中定义函数的这三种方法之间的差异

给出了表示同一函数 f(a) := a + 1的三种方法:

val f1 = (a:Int) => a + 1
def f2 = (a:Int) => a + 1
def f3:(Int => Int) = a => a + 1

这些定义有何不同? REPL 没有指出任何明显的差异:

scala> f1
res38: (Int) => Int = <function1>
scala> f2
res39: (Int) => Int = <function1>
scala> f3
res40: (Int) => Int = <function1>
19255 次浏览

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.

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)

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