匿名函数的`def`和`var/val`之间有什么区别?
在匿名函数中,使用def
和var/val
有什么区别?
val
声明了一个 "不可变的变量或者说是符号",不允许重新赋值,赋值语句的右侧会立即被计算。
var
声明了一个 "可变的变量",允许以后重新赋值给该变量,赋值语句的右侧会立即被计算,和val
类似。
def
声明了一个 "不可变的符号",不允许重新赋值,赋值语句的右侧被懒惰地计算,即在代码中稍后引用该符号时计算。
例如:
var plusOneVar = (x:Int) => x+1 val plusOneVal = (x:Int) => x+1 def plusOneDef = (x:Int) => x+1 plusOneVar = (x:Int) => x+2 // 可以重新赋值给var plusOneVal = (x:Int) => x+2 // 编译时错误,不能重新赋值给val plusOneDef = (x:Int) => x+2 // 编译时错误,不能重新赋值给def
因为你正在看一个函数的示例,很难理解。让我们尝试用简单的变量来理解。
var symbolVar = 100 // 第一行 val symbolVal = symbolVar // 第二行 def symbolDef = symbolVar // 第三行 println(symbolVar) // 输出 100 println(symbolVal) // 输出 100 println(symbolDef) // 输出 100 - 还没有惊喜 symbolVar = symbolVar + 1 println(symbolVal) // 仍然输出 100,因为它在第二行被计算和赋值 println(symbolDef) // 输出 101,因为symbolDef是一个def,它依赖于symbolVar,第三行被重新计算
问题出现的原因是在于理解匿名函数的定义和使用中,使用def
和val/var
的区别。解决方法是进行实例化和调用测试。
在代码中,使用def
定义了一个匿名函数f
,该函数接受一个Int
类型的参数i
,并返回i+1
。然后使用val g = f _
将函数f
赋值给g
。
通过测试我们可以发现,使用def
定义的匿名函数每次调用都会创建一个新的实例,而使用val
定义的匿名函数只会创建一个实例,并且可以被多次调用。
下面我们通过实例化和调用来验证这一结论:
def f (i:Int) = i+1
val g = f _
println(f(1)) // 输出:2
println(g(2)) // 输出:3
println(g(3)) // 输出:4
从上面的输出结果可以看出,使用def
定义的匿名函数每次调用都会创建一个新的实例,而使用val
定义的匿名函数只会创建一个实例,并且可以被多次调用。
因此,def
和val/var
在匿名函数的定义和使用中是有区别的。