本文来自:
John D. Cook 给对象和闭包(closure)下过一个经典的定义:“Anobject is data with functions. A closure is a function with data”[[1]] ,可以看到,闭包是由函数和运行时的数据决定的,闭包也因此被称为Lambda函数。事实上,闭包可以理解为函数和上下文,例如:
scala> var i=15
i: Int = 15
//定义一个函数字面量f,函数中使用了前面定义的变量i
scala> val f=(x:Int)=>x+i
f: Int => Int = <function1>
//执行函数
scala> f(10)
res0: Int = 25
//变量重新赋值
scala> i=20
i: Int = 20
//执行函数
scala> f(10)
res1: Int = 30
代码valf=(x:Int)=>x+i定义了一个函数字面量,函数中使用了自由变量i,变量i在程序的运行过程中会发生变量,在函数执行时如调用f(10)时会根据运行时变量i的值不同,得到不同的运行结果。自由变量i在运行过程中会不断发生变化,它处于一种开放状态,而当函数执行时,自由变量i的值已经被确定下来,此时可以认为在运行时它暂时处于封闭状态,这种存在开放到封闭过程的函数被称为闭包。函数字面量val f=(x:Int)=>x+i中便是函数(f)+上下文(自由变量i)的结合。
val f=(x:Int)=>x+i只是函数闭包的一种形式,高阶函数也可以理解为一种闭包,例如:
//高阶函数a,函数有两个参数:函数类型Double=>Double的参数f、Double=>Unit的参数p
scala> def a(f:Double=>Double,p:Double=>Unit)={
valx=f(10)
p(x)
}
a: (f: Double => Double, p: Double =>Unit)Unit
//定义一个输入参数为Double,返回值类型为Double的函数
scala> val f=(x:Double)=>x*2
f: Double => Double = <function1>
//定义一个输入参数为Double,返回值类型为Unit的函数
scala> val p=(x:Double)=>println(x)
p: Double => Unit = <function1>
//将定义的函数f、p作为高阶函数a的参数
scala> a(f,p)
20.0
定义另外一个输入参数为Double,返回值类型为Double的函数
scala> val f2=(x:Double)=>x*x
f2: Double => Double = <function1>
//将定义的函数f2、p作为高阶函数a的参数
scala> a(f2,p)
100.0
代码
def a(f:Double=>Double,p:Double=>Unit)={
valx=f(10)
p(x)
}
定义了高阶函数a,该函数使用两个不同函数类型作为参数,f:Double=>Double表示函数f的参数类型为Double、返回值类型为Double,p:Double=>Unit表示函数p的参数类型为Double,返回值类型为Unit。函数在运行时会根据传入的不同函数,得到不同运行结果,如执行a(f,p)和a(f2,p)得到的结果是不一样的,它也是由函数(高阶函数a)和上下文(传入的函数f、f2、p)构成的。