高阶函数
scala 混合了面向对象和函数式的特性,在函数式编程语言中,函数是“头等公民”,它和Int、String、Class等其他类型处于同等的地位,可以像其他类型的变量一样被传递和操作。
高阶函数包含
- 作为值的函数
- 匿名函数
- 闭包
- 柯里化等等
作为值的函数
在scala中,函数就像和数字、字符串一样,可以将函数传递给一个方法。我们可以对算法进行封装,然后将具体的动作传递给方法,这种特性很有用。
我们之前学习过List的map方法,它就可以接收一个函数,完成List的转换。
示例
示例说明
将一个整数列表中的每个元素转换为对应个数的小星星
List(1, 2, 3...) => *, **, ***
步骤
- 创建一个函数,用于将数字装换为指定个数的小星星
- 创建一个列表,调用map方法
- 打印转换为的列表
参考代码
val func: Int => String = (num:Int) => "*" * num
println((1 to 10).map(func))
匿名函数
定义
上面的代码,给(num:Int) => “*” * num函数赋值给了一个变量,但是这种写法有一些啰嗦。在scala中,可以不需要给函数赋值给变量,没有赋值给变量的函数就是匿名函数
val list = List(1, 2, 3, 4)
// 字符串*方法,表示生成指定数量的字符串
val func_num2star = (num:Int) => "*" * num
print(list.map(func_num2star))
示例
使用匿名函数优化上述代码
参考代码
println((1 to 10).map(num => "*" * num))
// 因为此处num变量只使用了一次,而且只是进行简单的计算,所以可以省略参数列表,使用_替代参数
println((1 to 10).map("*" * _))
柯里化
在scala和spark的源代码中,大量使用到了柯里化。为了后续方便阅读源代码,我们需要来了解下柯里化。
定义
柯里化(Currying)是指将原先接受多个参数的方法转换为多个只有一个参数的参数列表的过程。
柯里化过程解析
示例
示例说明
- 编写一个方法,用来完成两个Int类型数字的计算
- 具体如何计算封装到函数中
- 使用柯里化来实现上述操作
参考代码
// 柯里化:实现对两个数进行计算
def calc_carried(x:Double, y:Double)(func_calc:(Double, Double)=>Double) = {
func_calc(x, y)
}
def main(args: Intrray[String]): Unit = {
println(calc_carried(10.1, 10.2){
(x,y) => x + y
})
println(calc_carried(10, 10)(_ + _))
println(calc_carried(10.1, 10.2)(_ * _))
println(calc_carried(100.2, 10)(_ - _))
}
闭包
闭包其实就是一个函数,只不过这个函数的返回值依赖于声明在函数外部的变量。
可以简单认为,就是可以访问不在当前作用域范围的一个函数。
示例一
定义一个闭包
val y=10
val add=(x:Int)=>{
x+y
}
println(add(5)) // 结果15
add函数就是一个闭包
示例二
柯里化就是一个闭包
def add(x:Int)(y:Int) = {
x + y
}
上述代码相当于
def add(x:Int) = {
(y:Int) => x + y
}