简介
函数是一等公民,可以作为参数传入其他的函数中去。函数的返回值可以是函数,函数甚至可以嵌套函数。
- scala 中的高阶函数可以被称为函数值(function value)
- 闭包 是函数值的一种特殊形式,会捕获或者是绑定到另外一个作用域或者是上下文中定义的变量。
简单点理解
函数就是和其他的数据类型一样,可以赋值给变量,也可以作为参数传递给另外一个变量。
常规函数的局限
举例,我们要算出从1 到给定整数number 区间内所有整数的总和。
def sum(number:Int) = {
var result = 0
for (i <- 1 to number ){
result +=1
}
result
}
局限性
- 这段代码其实是不可扩展的,如果要额外的计算出给定区间 偶数的个数。就会出现问题。
解决方案
使用函数式风格,不是命令式的风格来处理这个问题。其实就是传递一个匿名函数(传递一种新的处理逻辑)利用这个中间层,在迭代中完成不同的任务。
可扩展性与高阶函数
什么是高阶函数
我们称将其他函数作为参数的函数为高阶函数
使用高阶函数(函数值)可以使我们的代码符合 DRY 原则。Don‘t repeat Yourself 的原则。
在scala 中创建特殊的实例处理函数值,这里的函数值其实就是对象。
使用函数式编程的思想,上一个例子我们抽象出公共的代码
totalResultOverRange(number:Int,codeBlock:Int =>Int) = {
var result = 0
for (i <- 1 to number) {
result +=codeBlock(i)
}
result
}
说明:
遍历区间内的数值,并且对每个元素调用 由变量codeBlock引用的函数,这个给定的函数期望接受一个表示区间内元素的Int,并返回Int作为该元素上的计算结果。
=> 符号
左边定义了匿名函数的预期输入类型。右边指定了函数的预期输出类型。
可以理解为
输入=>输出
匿名函数的作用其实就是接受输入,并且转化为输出且不会产生任何副作用的过程。
package TestFunc
object TestTotal {
def main(args: Array[String]): Unit = {
println(totalResultOverRange(11, i => if(i % 2 == 0 )i else 0))
}
def totalResultOverRange(number :Int,codeBlock: Int =>Int) = {
var result = 0
for (i <- 1 to number ) {
println(codeBlock(i))
result += codeBlock(i)
}
result
}
}
在这个例子中,如果输入是偶数,那么作为参数传入的函数值,会返回输入本身。否则返回0。
具有多个参数的函数值(高阶函数)
高阶函数其实可以接受零个或者是多个参数。
参数占位符
在scala 中 会用 _ 下划线表示函数值得参数。
注意: 只有打算在这个函数值中只引用这个参数一次的时候才可以这样做。
names.map(word => word.toUpperCase)
names.map(_.toUpperCase)
这两种情况是一样的效果
map 和 flatmap 说明
map(func)函数会对每一条输入进行指定的func操作,然后为每一条输入返回一个对象;而flatMap(func)也会对每一条输入进行执行的func操作,然后每一条输入返回一个相对,但是最后会将所有的对象再合成为一个对象;从返回的结果的数量上来讲,map返回的数据对象的个数和原来的输入数据是相同的,而flatMap返回的个数则是不同的。请参考下图进行理解:
补充说明
匿名函数:其实就是一个只有参数和实现的函数。也叫即时函数。