6.Scala-高阶函数

第6章 高阶函数

6.1 作为参数的函数

函数作为一个变量传入到另一个函数中,那么该作为参数的函数的类型是:function1,即:

(参数类型)=> 返回值

//6.1 作为参数的函数
def plus(x: Int) = 3 + x
val 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 -7
val result2 = highOrderFunction1(minus7)
println(result2)
 
2)高阶函数同样可以返回函数类型
def minusxy(x: Int) = (y: Int) => x - y
val 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 - y
println(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 - y
val f1 = minusxy(10)
val f2 = minusxy(10)
println(f1(3) + f2(3))

此处 f1,f2 这两个函数就叫闭包 。

6.6 柯里化

函数编程中,接受多个参数的函数都可以转化为接受单个参数的函数,
这个转化过程就叫柯里化,柯里化就是证明了函数只需要一个参数而已。
 
1)柯里化示例
// 传统定义两个参数
def mul(x:Int, y: Int) = x * y
println(mul(6,7))

// 柯里化定义,使用到了闭包
def mulOneAtATime(x: Int) = (y: Int) => x * y
println(mulOneAtATime(6)(7))

// Scala 中可以简写
def mulOneAtATime(x: Int)(y: Int) = x * y
println(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): Boolean
println(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

猜你喜欢

转载自www.cnblogs.com/LXL616/p/11122087.html
今日推荐