开发者学堂课程【Scala 核心编程 - 进阶:高阶函数的介绍和使用】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/610/detail/9091
高阶函数的介绍和使用
内容介绍:
一、匿名函数
二、高阶函数基本介绍
三、高阶函数基本使用
四、运行高阶函数
五、高阶函数可以返回函数的类型
一、匿名函数
请编写一个匿名函数,可以返回2个整数的和,并输出该匿名函数的类型.
//下面的f1就可以是一个匿名函数,调用的时候通过匿名函数传参就可以了,如果不传参数就代表输出这个类型,传上参数就代表调用这个匿名函数。
val f1 = (n
1
: lnt,n2: Int ) => {
println("匿名函数被调用")
n1 +n2
}
println("f1类型=”+ f1)
println(f1(10,30))
传上参数代表调用匿名函数,不传参数就代表输出类型。
二、高阶函数基本介绍
高阶函数除了可以接受一个函数之外,他还可以返回一个函数,这是他很重要的特色。高阶函数能够接受函数作为参数的函数,叫做高阶函数(higher-order function)。
可使应用程序更加健壮。高阶函数可以接收一个函数也可以返回一个函数。
三、高阶函数基本使用
//test 就是一个高阶函数,它可以接收 f: Double =>
Double
Def
test(f: Double => Double, n1: Double)= {
f(n1) (这里的test函数可以接收一个高阶函数,这个函数的类型是传入double返回double要匹配,后面传入一个普通的参数,在里面调用一个传入的函数并去执行它。)
}
/
/sum是接收一个Double,返回一个Double
def sum(d: Double): Double ={
d + d
}
sum 函数接受一个打包返回一个 double 的案例,调用的时候很简单,就是test,把sum 函数传进去,再把6.0传进去,6.0传入到了n1,这个n1又传入到了传入的函数去执行,逻辑是很清晰的。
val res = test(sum, 6.0)
//6.0传入n1
println("res=" + res)
四、运行高阶函数
创建新的 Scala Class,name 为 HigherOrderFunction,Kind 为 Object。
把6.0传给 sum,在底层 text 里面调,sum 将地址传给f1。f指向了Sum的地址,大致的逻辑是6.0传给了 n1,传完之后 sum 是有地址的,Sum 将地址传给f1,到了执行test的时候,因为f1的地址指向了sum,所以会到 sum 这边来执行,N1会被传入到f(n1),执行结束以后,把结果返回给test.
object HigherorderFunction {
def main(args : Array[string]): unit = {
def test(f: Double => Double,n1: Double) = {
f(n1)
}
/
/ sum是接收一个Double,返回一个Double
def sum( d: Double): Double ={
d + d
}
val res = test( sum,6.
0
)
//
println( "res=" +res)
/
/
结果为
12.0
object HigherorderFunction {
def main( args : Array [string]): unit = {
def test(f: Double => Double,f2: Double =>Int , n1: Double) = {
f(f2(n
1
)) /
/f(0)
}
//
sum是接收一个Double,返回一个Double
Def
sum(d: Double): Double = {
d + d
}
问题:高阶函数里面能不能再调用一个函数?
在此处做一个扩展,如果对f1做一个取模的操作,取模过后再传给f,那么这个过程可不可以呢?
通过以下过程进行验证
Def函数用来把double转成int再返回取模的值,假如写成以下函数,同时改写上面代码为 def test(f: Double => Double,f2: double =>Int,n1:Double)= { f2传进来是一个 double 类型,double 类型返回的是 int 类型。
先把 f1传给 f2,把n1再传进去,即f(f2(n1)),下方再传入一个 mod,所以在这个地方不能认为只能传入一个高阶函数,而是可以传入多个函数,函数之间也可以进行调用,这样功能就会更加倍拓展,比如在高阶函数里面使用集合的map、reduce等等,如果以后再用的时候用到匿名函数,可能传入的不是一个函数,可能会传入多个函数。
def mod(d: Double): Int = {
d.toInt %2
}
val res = test(sum,mod,6.o)
//
println( "res=" +res)
//
0.0
}
}
首先把6.0
传给了f2,f2是mod,mod把6.0先取整在模2,应该等于0,只要结果是0.0,那就说明代码是正确的。
运行结果如下:
Res
=0.0
Process finished with exit code
0
五、高阶函数可以返回函数的类型
函数的闭包就是由高阶函数可以返回函数的类型引起的。高阶函数不仅可以接受一个函数,也可以返回一个函数,返回还可以继续执行。
代码放进去显示错误,但是实际上是没有错误的,这种错误一般是由于特殊字符导致的,有的时候拷贝过来之后发现会出现错误,那就首先要看有没有特殊字符最好的方法就是重新输入一遍。
或者是在桌面新建一个文本文件,打开后把复制的代码放入新建的文本文件,可以打到一个去格式化的目的,保存然后再进行复制粘贴即可。除此之外,还有一个小技巧,在文本文件里面打开视图,选择空白,点击全部,可以看到所有的制表符。
新建新的Scala Class,name为HigherOrderfuncton2,Kind为Object。
object HigherorderFunction2 {
def main( args : Array[string]) : unit = {
def minusxy(x: Int) = {
(y: Int) => x-y//匿名函数}
val result3 = minusxy(3)(5)
println( result3)
//说明
//1. minusxy 是高阶函数,因为它返回匿名函数
//2.返回的匿名函数是(y: Int) =>X-y,它还用到了minusxy传进来的x,这个地方有一个特殊语法叫闭包。
// 3.返回的匿名函数可以使用变量接收
def minusxy(x: Int)= {
(y: Int)=> x
-y//
匿名函数
}
//分步执行
//f1就是(y,int)=>3-y,3是固定不变的,每次调用都是3
val result3 = minusxy(3)
println(""f1的类型“ + f1)
println(f1(1))//2(y是动态填进去的,调用的是(y,int),和minusxy没有关系了,看里面的代码)
运行结果为:
res=2.0
println(f1(9))//-6(9在调用的时候仍然是用的(y,int)=>3-y)
运行结果为:res=-6
f1的类型是Function1,因为它的形参是一个。
//也可以一步到位的调用
printLn(minusxy(4)(9))// -5
先执行minusxy(4),相当于返回了一个匿名函数,而且没有变量接收,相当于是4-y,因为后面又传入了一个9,9就是y,就变成了4-9,结果就是-5.