定义一个函数“def”和“val”有什么不同?

有什么区别:

def even: Int => Boolean = _ % 2 == 0 

 val even: Int => Boolean = _ % 2 == 0 

两者都可以称为even(10)

方法def even每次调用都会创build新的函数( Function1新实例)。

 def even: Int => Boolean = _ % 2 == 0 even eq even //Boolean = false val even: Int => Boolean = _ % 2 == 0 even eq even //Boolean = true 

通过def您可以在每个通话中获得新的function:

 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指出你可以定义方法,这是最快的select:

 def even(i: Int): Boolean = i % 2 == 0 

但是,如果你需要一个函数组成的函数(而不是方法)或者更高阶的函数(比如filter(even) ),编译器会在你每次使用函数的时候从你的方法中生成一个函数,所以性能可能会比val

考虑一下:

 scala> def even: (Int => Boolean) = { println("def"); (x => x % 2 == 0) } even: Int => Boolean scala> val even2: (Int => Boolean) = { println("val"); (x => x % 2 == 0) } val //gets printed while declaration. line-4 even2: Int => Boolean = <function1> scala> even(1) def res9: Boolean = false scala> even2(1) res10: Boolean = false 

你看得到差别吗? 简而言之:

def :对于每个调用even ,它再次调用even方法的主体。 但是,对于even2val) ,函数在声明时仅初始化一次(因此它在第4行打印val ,而不再次),每次访问时都使用相同的输出。 例如尝试这样做:

 scala> import scala.util.Random import scala.util.Random scala> val x = { Random.nextInt } x: Int = -1307706866 scala> x res0: Int = -1307706866 scala> x res1: Int = -1307706866 

x被初始化时,由Random.nextInt返回的值被设置为x的最终值。 下一次x再次使用,它将始终返回相同的值。

你也可以懒洋洋地初始化x 。 即第一次使用它是初始化,而不是在声明时。 例如:

 scala> lazy val y = { Random.nextInt } y: Int = <lazy> scala> y res4: Int = 323930673 scala> y res5: Int = 323930673 

看到这个:

  var x = 2 // using var as I need to change it to 3 later val sq = x*x // evaluates right now x = 3 // no effect! sq is already evaluated println(sq) 

令人惊讶的是,这将打印4而不是9! val(偶数var)立即求值并赋值。
现在改变val去def ..它会打印9! Def是一个函数调用,它将在每次调用时进行评估。

Val也是一个价值评估。 这意味着在定义期间评估右手表情。 Def是通过名称评估。 它不会评估,直到它被使用。