有什么区别:
def even: Int => Boolean = _ % 2 == 0
Run Code Online (Sandbox Code Playgroud)
和
val even: Int => Boolean = _ % 2 == 0
Run Code Online (Sandbox Code Playgroud)
两者都可以称为even(10).
sen*_*nia 316
方法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
Run Code Online (Sandbox Code Playgroud)
有了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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
请注意,还有第三种选择:lazy val.
它在第一次调用时进行评估:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
Run Code Online (Sandbox Code Playgroud)
但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
Run Code Online (Sandbox Code Playgroud)
性能
val 评估何时定义.
def评估每个呼叫,因此性能可能比val多个呼叫更差.只需一次通话即可获得相同的性能.没有任何调用你就不会有任何开销def,所以你可以定义它,即使你不在某些分支中使用它.
有了lazy val你会得到一个懒惰的评价:你可以定义它,即使你不会在某些分支中使用它,它会评估一次或从不,但你会得到一点点开销,双重检查锁定每次访问你的lazy val.
正如@SargeBorsch指出你可以定义方法,这是最快的选择:
def even(i: Int): Boolean = i % 2 == 0
Run Code Online (Sandbox Code Playgroud)
但是如果你需要一个函数(不是方法)用于函数组合或更高阶函数(比如filter(even)),编译器会在你每次将它作为函数使用时从你的方法生成一个函数,所以性能可能会稍微差一些val.
Jat*_*tin 23
考虑一下:
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
Run Code Online (Sandbox Code Playgroud)
你看得到差别吗?简而言之:
def:对于每次调用even,它even再次调用方法的主体.但是使用even2ie val,函数在声明时只初始化一次(因此它val在第4行打印而且从不再打印)并且每次访问时都使用相同的输出.例如,尝试这样做:
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
Run Code Online (Sandbox Code Playgroud)
当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
Run Code Online (Sandbox Code Playgroud)
看到这个:
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)
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,它将打印4而不是9!val(偶数var)将立即求值并赋值。
现在将val更改为def ..它将打印9!Def是一个函数调用。它将在每次调用时求值。
| 归档时间: |
|
| 查看次数: |
55149 次 |
| 最近记录: |