1. 程式人生 > >Scala 高階函式

Scala 高階函式

1.作為引數的函式

    函式作為一個變數傳入到了另一個函式中,那麼該作為引數的函式的型別是:function1,即:(引數型別) => 返回型別

def plus(x: Int) = 3 + x

val result1 = Array(1, 2, 3, 4).map(plus(_))

println(result1.mkString(“-"))

    注:帶有一個引數的函式的型別是function1,帶有兩個是function2,以此類推

2.匿名函式

    即沒有名字的函式,可以通過函式表示式來設定匿名函式。

//即沒有名字的函式,可以通過函式表示式來設定匿名函式。

val triple = (x: Int) => 3 * x

println(triple(3))

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)

4.引數(型別)推斷

// 傳入函式表示式

highOrderFunction1((x: Double) => 3 * x)

// 引數推斷省去型別資訊

highOrderFunction1((x) => 3 * x)

// 單個引數可以省去括號

highOrderFunction1(x => 3 * x)

// 如果變數旨在=>右邊只出現一次,可以用_來代替

highOrderFunction1(3 * _)

5. 閉包

    閉包就是一個函式把外部的那些不屬於自己的物件也包含(閉合)進來。

def minusxy(x: Int) = (y: Int) => x - y

這就是一個閉包:

(1)匿名函式(y: Int) => x -y巢狀在minusxy函式中。

(2)匿名函式(y: Int) => x -y使用了該匿名函式之外的變數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.柯里化

    函式程式設計中,接受多個引數的函式都可以轉化為接受單個引數的函式,這個轉化過程就叫柯里化,柯里化就是證明了函式只需要一個引數而已。其實我們剛才的學習過程中,已經涉及到了柯里化操作,所以這也印證了,柯里化就是以函式為主體這種思想發展的必然產生的結果。

(1)柯里化示例

def mul(x: Int, y: Int) = x * y

println(mul(10, 10))

 

def mulCurry(x: Int) = (y: Int) => x * y

println(mulCurry(10)(9))

 

def mulCurry2(x: Int)(y:Int) = x * y

println(mulCurry2(10)(8))

(2)柯里化的應用

    比較兩個字串在忽略大小寫的情況下是否相等,注意,這裡是兩個任務:

        ① 全部轉大寫(或小寫)

        ② 比較是否相等

    針對這兩個操作,我們用一個函式去處理的思想,其實無意間也變成了兩個函式處理的思想。示例如下:

val a = Array("Hello", "World")

val b = Array("hello", "world")

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

}

    注:不要設立柯里化存在的意義這樣的命題,柯里化,是面向函式思想的必然產生結果。

7.控制抽象

      控制抽象是一類函式:

      引數是函式。

      函式引數沒有輸入值也沒有返回值。

(1)使用示例

def runInThread(f1: () => Unit): Unit = {

  new Thread {

    override def run(): Unit = {

      f1()

    }

  }.start()

}

 

runInThread {

  () => println("幹活咯!")

  Thread.sleep(5000)

  println("幹完咯!")

  }

    是不是很爽?是不是有點類似執行緒池的感覺,同一個執行緒,可以動態的向裡面塞不同的任務去執行。可以再簡化一下,省略(),看下如下形式:

def runInThread(f1: => Unit): Unit = {

  new Thread {

    override def run(): Unit = {

      f1

    }

  }.start()

}

 

runInThread {

  println("幹活咯!")

  Thread.sleep(5000)

  println("幹完咯!")

  }

(2)進階用法:實現類似while的until函式

def until(condition: => Boolean)(block: => Unit) {

  if (!condition) {

    block

    until(condition)(block)

  }

}

 

var x = 10

until(x == 0) {

  x -= 1

  println(x)

}