定义一个函数“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
方法的主体。 但是,对于even2
即val) ,函数在声明时仅初始化一次(因此它在第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是通过名称评估。 它不会评估,直到它被使用。