Scala函数式编程(六)——闭包

时间:2021-05-30 22:41:05

本文来自:周志湖老师:Scala学习


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、返回值类型为Doublep:Double=>Unit表示函数p的参数类型为Double,返回值类型为Unit。函数在运行时会根据传入的不同函数,得到不同运行结果,如执行a(f,p)a(f2,p)得到的结果是不一样的,它也是由函数(高阶函数a)和上下文(传入的函数ff2p)构成的。