方法def even 每次调用都会评估并创建新函数(Function1 的新实例)。
def even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = false
val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
使用def,您可以在每次调用时获得新功能:
val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1049057402
test()
// Int = -1049057402 - same result
def test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val 在定义时评估,def - 在调用时:
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
scala> def even: Int => Boolean = ???
even: Int => Boolean
scala> even
scala.NotImplementedError: an implementation is missing
请注意,还有第三个选项:lazy val。
它在第一次调用时进行评估:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
但每次都返回相同的结果(在本例中为 FunctionN 的相同实例):
lazy val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
lazy val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1068569869
test()
// Int = -1068569869 - same result
性能
val 在定义时进行评估。
def 对每次调用进行评估,因此多次调用的性能可能比val 差。一次调用即可获得相同的性能。在没有调用的情况下,您不会从def 获得任何开销,因此即使您不会在某些分支中使用它,您也可以定义它。
使用lazy val,您将得到一个惰性评估:即使您不会在某些分支中使用它,您也可以定义它,并且它评估一次或从不评估,但您会从双重检查锁定中获得一点开销每次访问您的lazy val。
正如@SargeBorsch 所说,您可以定义方法,这是最快的选择:
def even(i: Int): Boolean = i % 2 == 0
但是,如果您需要一个函数(不是方法)来进行函数组合或更高阶函数(如filter(even)),每次您将其用作函数时,编译器都会从您的方法中生成一个函数,因此性能可能会稍差比val.