Scala系列6、scala的高阶函数
1.=> 表示对左边的参数进行右边的加工
2.关于对scala函数中的参数可以传函数的理解(带函数参数的函数):
eg: def value(f: (Double) => Double) = f(0.25)
//(参数类型) => 结果类型
可以按照一般的参数去理解:这个带函数参数的函数,要求我们传入的参数是一个函数。例如我们传入scala.math.ceil
value(ceil _) //结果是1
整个过程可以这样解释:首先函数判断传入的参数是否匹配,我们按照要求传入了一个函数作为参数;然后传入的函数就相当于函数定义时的f();那就意味着我们其实在value中做了一个ceil(0.25)的运算。
3.函数和方法的区别
使用def定义一个方法;
函数:val fun = (x: Double) => x + 1
【函数式编程】
scala函数式编程是scala中的重中之重,spark当中的计算都是用scala函数编程来做的。
这里我们定义一个fun方法,然后将其赋值给一个常量 fun_v。赋值的格式是: val 变量名 = 函数名+空格+_ 这里的函数名后面必须要加空格,表明是函数的原型。这样我们就把一个函数赋值给变量了,fun_v会接收一个string类型的参数并打印。(=>表示对左边的参数进行右边的加工)
//控制台打印的效果
scala> def fun(name:String){println(name)}
fun: (name: String)Unit
scala> val fun_v = fun _
fun_v: String => Unit = $$Lambda$1013/[email protected]
scala> fun_v("scala")
scala
【函数闭包】
关于函数的闭包,看了很多教程但是都没有太理解。但是在这个过程中也形成了一点自己的认知,现在记录下来。
首先说下JavaScript中的闭包,在没有更好的理解scala闭包这个概念之前,先理解js的闭包。
js中的闭包,就是变量解析的过程。每次定义一个函数,都会产生一个作用域链(scope chain)。当js寻找变量时(这个过程称为变量解析),总会优先在当前作用域的第一个对象中查找这个变量,如果找到,则直接使用这个变量;否则,继续查找下一个对象中是否存在这个变量;这个过程会持续到最终找到这个变量或者引发错误为止。
下面图中说的“scopechain是一个有顺序的集合对象”这句话,是这样理解的:结合上图的注释,在welcome函数的作用域内存在多个对象,每个对象都有作用域,这样就构成了一个有顺序的集合,因为程序都是从上往下依次运行。
再来看一个scala中的例子:
def mulBy(factory: Double) = (x: Double) => factory * x
//或者是这种形式
def mulBy(factory: Double) = {
(x: Double) => factory * x
}
上面的截图说明了一个问题:mulBy函数需要两个参数,返回值是Double。所以我们在调用的时候可以这样调用
mulBy(3)(3)
也可以这样调用
val triple = mulBy(3)
triple(3)
mulBy(3)将参数factory的值设置为3。“val triple = mulBy(3)”这一步就相当于:val triple = (x: Double) => 3 * x 所以triple(3)的结果就是9
上面这是对于scala中这种函数形式的理解。再来看一个例子:
这时scala会报错说找不到y这个值。原因很明显,我们根本就没有定义y。接下来我们定义一个y。再次定义sum函数,并运行
此时sum的结果是10,这是因为我们在值函数外面声明了一个全局变量y,然后在运行sum函数时就会捕获这个全局变量,从而使得x+y变成一个正常的函数定义,让函数的定义闭合起来,这就是闭包。闭包如何实现不重要,scala编译器会确保我们的函数可以访问非局部变量。
闭包的实质就是代码与用到的非局部变量的混合,即:
闭包=代码+用到的非局部变量
【柯里化】
关于函数闭包中我们已经窥见了柯里化的一点影子。柯里化指的是将原来接受两个参数的函数变成新的接受一个参数的函数过程。新的函数返回一个以原有第二个参数作为参数的函数。
恩?我们来看一个示例:
def mul(x: Int, y: Int) = x * y
经过柯里化,原来需要接受两个参数的函数现在接受一个,生成另一个接受单个参数的函数
def mulOneAtATime(x: Int) = (y: Int) => x * y
调用方法是: mulOneAtATime(6)(7)。mulOneAtATime(6)的结果是函数(y:Int) => 6 * y。而这个函数又被应用到7,因此最终结果是42。
我们也可以简写定义柯里化函数
def mulOneAtATime(x: Int)(y: Int) = x * y
关于更详尽的函数柯里化,请参看博客:http://blog.csdn.net/sufubo/article/details/51536757