函数
函数是绑定了值,或用其它表达式替换变量时可被求值或应用(apply)的计算行为的抽象。
函数是一种具名或匿名的操作,其代码直到调用时才执行。在函数定义中,可能有也可能没有引用外部的自由变量(也即在函数定义之外定义的变量)。
闭包
闭包是一个在其定义中包含自由变量的函数,可能具名也可能匿名,并通过包含环境信息以绑定其引用的自由变量。
var factor = 2
val multiplier = (i: Int) => i * factor //定义一个闭包
multiplier(2) //4
factor = 3
multiplier(2) //6
factor并不是multiplier的参数,而是一个自由变量,是一个当前作用域中某个值的引用。所以,编译器创建了一个闭包,用于包含(或覆盖)multiplier与它引用的外部变量的上下文,从而就绑定了外部变量本身。由于multiplier引用了factor,每次调用时都会重新读取factor的值,所以当factor发生变化时multiplier也会跟着变化。
def factory: Int => Int = {
var factor = 2
val multiplier = (i: Int) => {
factor += 1
i * factor
}
multiplier
}
val multiplier = factory //返回一个闭包
multiplier(2) //6
multiplier(2) //8
当factor处于某个局部作用域(或某个方法)中,而将multiplier传递给其它作用域(或其它方法)时,上述机制依然有效,且自由变量factor的有效性会一直伴随着multiplier函数。
匿名函数
若函数非具名,则称其为匿名函数,在Scala也可将之称为Lambda函数或函数字面量。
用Lambda函数表示匿名函数来源于Lambda微积分,在Lambda微积分中用希腊字母Lambda(λ)来表示匿名函数。
Alonzo Chruch在数学的可计算理论中首先研究了Lambda微积分,在Lambda微积分中,将函数的特性总结为:函数是绑定了值,或用其它表达式替换变量时可被求值或应用(apply)的计算行为的抽象(apply一词就是我们Scala中经常用到的默认方法apply名字的来源)。
Lambda微积分也为函数表达式的简化、如何用值代替变量等定义了规则。
val double = (i: Int) => i * 2 //将匿名函数定义为一个值double
参考《Scala程序设计》第二版