一、函数的闭包
1.闭包的概念
闭包:如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包
在下面这个函数中,func和f1执行完毕后都从JVM的stack中弹出了,为什么执行f2时还能访问到func和f1中的变量值呢?与Java不同的是,在Scala中函数也是一个对象,当我们调用了一个函数时,相当于在JVM的heap中创建了一个对应的对象实例,所依赖的外部环境和局部变量都保存在这个实例里,这就是所谓的闭包保存的实体
def func(i: Int): String=>(Char=>Boolean) = {
def f1(s: String): Char=>Boolean = {
def f2(c: Char): Boolean = {
if (i == 0 && s == "" && c == '0') false else true
}
f2
}
f1
}
2.闭包的应用
我们可以利用函数闭包以及可以将函数作为返回值的特性,来,比如有一批数据需要进行加4操作,另一批数据需要进行加5操作,核心操作一样但是固定参数不一样,这时我们就可以通过在一个外层函数中传入不同的参数(比如4或5)返回得到对应需求的函数
def addByA(a: Int): Int=>Int = {
def addB(b: Int): Int = {
a + b
}
addB
}
//根据传入的参数得到不同的函数
val addByFour2 = addByA(4)
val addByFive2 = addByA(5)
//利用得到的函数再去进行数据操作
println(addByFour2(13))
println(addByFive2(25))
二、函数的柯里化
1.柯里化的概念
函数柯里化:把接受多个参数的函数变换成接受一个参数(最初函数的第一个参数)的函数,并将函数的返回值修改为接收剩余参数执行原函数体的函数,如果剩余参数有多个,这个接受剩余参数的函数还可以继续进行柯里化。
对于柯里化后的函数,当我们一次传入所有参数时,其功能特性就和柯里化前一样返回一样的值,但是当我们只传入前几个参数时,我们就可以得到一个接收剩余参数的函数,这就提供了很大的灵活性。
2.柯里化的应用
比如上述例子中的addByA函数,我们就可以用柯里化来替代实现
def add(a: Int, b: Int): Int = {
a + b
}
//对add()进行柯里化
def addCurrying(a: Int)=(b: Int): Int = {
a + b
}
//可简写为
def addCurrying1(a: Int)(b: Int) = a + b
//只传入第一个参数,就得到一个以b为参数的函数(函数体中a固定为4)
val addByFour2 = addCurrying(4)
同样对于三个整数乘法的函数在scala中由于有柯里化的存在,自然有多种功能等价的函数定义形式,如以下四种函数都是实现了三个整数乘法功能,只不过调用不同形式参数过程略有不同,直接参入三个参数的一步到位就可以得到运算结果,而传入1或者2个参数的需要分步骤再传入第2/3或者第3个参数才能求出三个整数相乘的结果,很好地体现了延迟执行或者固定易变因素等方面能力。
def multiplie3par(x:Int,y:Int,z:Int)=xyz
def multiplie3par1(x:Int)=(y:Int,z:Int)=>xyz
def multiplie3par2(x:Int)(y:Int)(z:Int)=xyz
def multiplie3par3(x:Int)(y:Int)=(z:Int)=>xyz
编译执行的结果都是一样
参考文章:Scala中的柯里化