快学Scala-12-高阶函数
作为值的函数
Scala中可以在变量中存储函数
1 |
|
将num设置为3.14,将fun设置为一个函数_表明确实指定的是函数,而不是少传了参数。num的类型为Double,而fun的类型是(Double) => Double; 接受并返回Double的函数。
可以对函数进行调用或者传递
1 |
|
匿名函数
Scala中无需对每一个函数命名
1 |
|
def 定义的是方法,而不是函数
带函数参数的函数
函数/方法可以接受另一个函数做参数
1 |
|
这个方法的类型是((Double)=>Double) => Double
这类接受函数做参数的方法/函数就是高阶函数
高阶函数也可以产出另一个函数
1 |
|
参数(类型)推断
将匿名函数传递给另一个函数方法时,Scala会帮助推断类型信息,上面方法可以简写
1 |
|
一些有用的高阶函数
- map方法就是一个高阶函数,会对集合中的所有元素应用传入的方法
- foreach方法和map相似,但是foreach中的函数没有返回值,只讲函数应用到每一个值比如打印
- filter方法对集合元素进行筛选,传入一个boolean类型的函数
- reduceLeft方法接受一个二元函数(带有两个参数的函数),并将它应用在序列中的所有元素上
1
(1 to 6).reduceLeft(_*_) // 返回1*2*3*4*5*6
- sortWith接受一个boolean类型的二元函数,比较大小,对序列进行排序
闭包
Scala中可以在任何作用域内定义函数,包,类甚至另一个函数或方法里都可以。
函数体内可以访问到相应作用域的任何变量。并且函数可以在变量不再处于作用域内的时候调用。
1 |
|
执行过程如下:
- mulBy首次调用将参数factor设置为3,之后被函数引用,存入triple,之后参数变量factor从运行时的栈上弹出
- multy再次被调用,factor设置为0.5,被函数引用,存为half。factor弹出
每一个返回的函数都有自己的factor设置
这样的一个函数被称为闭包(closure),闭包由代码和代码用到的任何非局部变量定义构成。
这些函数实际以类的对象形式实现,该类由一个实例变量factor和一个包含了函数体的apply方法构成。
SAM转换
从Scala 2.12开始,可以将Scala函数传给预期接受一个“SAM接口”(任何带有单个抽象方法的Java接口)的Java代码。Java中这类接口称作函数式接口。
1 |
|
柯里化
指将原来接受两个参数的函数转化为新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数作为参数的函数。
1 |
|
Scala支持多组括号的形式来实现柯里化
1 |
|
利用柯里化将某个参数单独拎出来,以提供更多用于类型推断的信息
控制抽象
Scala中,可以将一系列语句组成不带参数也没有返回值的函数
1 |
|
想要省略掉表示空参数的(),可以这样
1 |
|
这就是控制抽象,看上去像是编程语言关键字的函数。比如我们可以定义一个until函数,作用和while类似
1 |
|
这样的函数参数叫做换名调用参数,和常规参数不同,函数在调用时参数表达式不会被求值,表达式称为无参函数的函数体,该函数被当成参数传递下去。
until函数时柯里化的,首先处理掉condition,然后把block当成另一个独立参数。
return表达式
Scala无需用return返回函数值,函数的返回值就是函数体最后的值。但可以用return从匿名函数中返回值给包含这个匿名函数的带名函数。
1 |
|
匿名函数 if(str(i) == ch) return i;i+=1 的值被传递给until,当return执行时,包含它的带名函数indexof终止并返回给定的值。
如果要在带名函数中使用return,需要给定其返回值类型。