第6章 高阶函数
6.1 作为参数的函数
函数作为一个变量传入到另一个函数中,那么该作为参数的函数的类型是:function1,即:
(参数类型)=> 返回值
//6.1 作为参数的函数def plus(x: Int) = 3 + xval result1 = Array(1, 2, 3, 4).map(plus(_))println(result1.mkString(","))
尖叫提示:带有一个参数的函数的类型是function1,带有两个参数的是function2,以此类推。
笔记:
//6.1 作为参数的函数def match1(): Unit = { def plus(x: Int) = 3 + x val result1 = Array(1, 2, 3, 4).map(plus(_)) println(result1.mkString(",")) //4,5,6,7}match1()
6.2 匿名函数
即没有名字的函数,可以通过函数表达式来设置匿名函数。
val triple = (x: Double) => 3 * x println(triple(3))//使用方法:Array(3.14, 1.42, 2.0).map(triple)//包含在()中Array(3.14, 1.42, 2.0).map((x: Double) => 3 * x)// 包含在{}中Array(3.14, 1.42, 2.0) map { (x: Double) => 3 * x }
笔记:
//6.2 匿名函数def match2(): Unit = { val triple = (x: Double) => 3 * x println(triple(3)) //9.0 //使用方法: println(Array(3.14, 1.42, 2.0).map(triple).mkString(", ")) //9.42, 4.26, 6.0 //包含在()中 println(Array(3.14, 1.42, 2.0).map((x: Double) => 3 * x).mkString(", ")) // 包含在{}中 println(Array(3.14, 1.42, 2.0) map { (x: Double) => 3 * x } mkString(", "))}match2()
6.3 高阶函数
能接受函数作为参数的函数,叫做 高阶函数。
1)高阶函数的使用
def highOrderFunction1(f: Double => Double) = f(10)def minus7(x: Double) = x -7val result2 = highOrderFunction1(minus7)println(result2)
2)高阶函数同样可以返回函数类型
def minusxy(x: Int) = (y: Int) => x - yval result3 = minusxy(3)(5)println(result3)
6.4 参数(类型)推断
// 传入函数表达式valueAtOneQuarter((x: Double) => 3 * x)// 参数推断省去类型信息valueAtOneQuarter((x) => 3 * x)// 单个参数可以省去括号valueAtOneQuarter(x => 3 * x)// 如果变量旨在=>右边只出现一次,可以用_来代替valueAtOneQuarter(3 * _)
6.5 闭包
闭包就是一个函数把外部的那些不属于自己的对象也包含(闭合)进来了。
def minusxy(x : Int) = (y : Int) => x - yprintln(minusxy(10)(20))
这就是一个闭包
1) 匿名函数(y : Int) => x - y 嵌套在函数 minusxy 中。
2) 匿名函数(x : Int) => x - y 使用了外部变量、mulBy 的局部变量 x。不是全局变量
3) 函数 minusxy 返回了引用局部变量的匿名函数。
再举一个例子:
def minusxy(x: Int) = (y: Int) => x - yval f1 = minusxy(10)val f2 = minusxy(10)println(f1(3) + f2(3))
此处 f1,f2 这两个函数就叫闭包 。
6.6 柯里化
函数编程中,接受多个参数的函数都可以转化为接受单个参数的函数,
这个转化过程就叫柯里化,柯里化就是证明了函数只需要一个参数而已。
1)柯里化示例
// 传统定义两个参数def mul(x:Int, y: Int) = x * yprintln(mul(6,7))// 柯里化定义,使用到了闭包def mulOneAtATime(x: Int) = (y: Int) => x * yprintln(mulOneAtATime(6)(7))// Scala 中可以简写def mulOneAtATime(x: Int)(y: Int) = x * yprintln(mulOneAtATime(10)(8))
2)柯里化的应用
比较两个字符串再忽略大小写的情况下是否相等,注意,这里是两个任务:
1、全部转大写(或小写)
2、比较是否相等
针对这两个操作,我们用一个函数去处理的思想,其实无意间也变成了两个函数处理的思想。
示例如下:
val a = Array("Hello", "World")val b = Array("hello", "world")// def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Booleanprintln(a.corresponds(b)(_.equalsIgnoreCase(_)))
corresponds 函数的定义使用了柯里化
源码如下:
def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Boolean = { val i = this.iterator val j = that.iterator while (i.hasNext && j.hasNext) if (!p(i.next(), j.next())) return false !i.hasNext && !j.hasNext }
6.7 控制抽象
控制抽象是一类函数:
1、参数是函数。
2、函数参数没有输入值也没有返回值。
1)使用示例:
def runInThread(block: () => Unit) { new Thread { override def run() { block() } }.start()} // 传入函数runInThread { () => println("Hi") ; Thread.sleep(10000); println("Bye") }() = > 有些多余,可以使用换名调用来表示,省略()保留=>// 这种叫控制抽象函数 (看上去像是编程语言关键字的函数)def runInThread(block: => Unit) { new Thread { override def run() { block } }.start()} // 优雅的传入runInThread { println("Hi") ; Thread.sleep(1000); println("Bye") } //可以定义类似于 while 的 until 函数def until(condition: => Boolean)(block: => Unit) { if (!condition) { block until(condition)(block) }} var x = 10 until (x == 0) { x -= 1 println(x) }
笔记:
//6.7 控制抽象def runOnThread(f1:() => Unit): Unit = { new Thread{ override def run(): Unit = { f1() } }.start()}runOnThread({ () => println("干活!") Thread.sleep(5000) println("活干完了!")})// () => 1; 2; 3 + 1