標籤:

Scala快速入門-9-高階函數

知識點

  • 作為值的函數
  • 創建匿名函數
  • 帶函數參數的函數
  • 閉包
  • 柯里化

函數

  • 在Scala中,函數是「頭等公民」,可以在變數中存放函數

scala> def fun(msg: String) {println(msg)}nfun: (msg: String)Unitnnscala> val f = funn<console>:8: error: missing arguments for method fun;nfollow this method with `_ if you want to treat it as a partially applied functionn val f = funn ^nnscala> val f = fun _nf: String => Unit = <function1>nnscala> f("Yezhiwei")nYezhiwei n

函數後面的 _ 意味著指的是這個函數

  • 作為參數傳遞給另一個函數

scala> Array("Hello", "Scala").map(f)nHellonScalanres2: Array[Unit] = Array((), ())n

map方法接受一個函數參數,將它應用到數組中的所有值,然後返回結果數據

  • 在Scala中,不需要給每一個函數命名,匿名函數

scala> (x: Double) => 3 * xnres3: Double => Double = <function1>n

  • 在Scala中,可以將上面的函數放到變數中

scala> val triple = (x: Double) => 3 * xntriple: Double => Double = <function1>nn與def一樣ndef triple = (x: Double) = 3 * xn

  • 可以將匿名函數直接傳遞給另一個函數

scala> Array(3.14, 1.42).map((x: Double) => 3 * x)nres4: Array[Double] = Array(9.42, 4.26)n

  • 帶函數參數的函數,如實現接受另一個Double並且返回Double的函數

scala> def fun(f: (Double) => Double) = f(0.25)nfun: (f: Double => Double)Doublennscala> import scala.math._nimport scala.math._nnscala> fun(ceil _)nres12: Double = 1.0nnscala> fun(sqrt _)nres13: Double = 0.5nn///////////nnscala> def mulBy(factor: Double) = (x: Double) => factor * xnmulBy: (factor: Double)Double => Doublennscala> val q = mulBy(5)nq: Double => Double = <function1>nnscala> q(20)nres14: Double = 100.0nn// val q = mulBy(5) 相當於 val q = (x: Double) => 5 * xn

  • 將一個匿名函數傳遞給另一個函數或方法時,Scala會儘可能推斷出類型信息

scala> def fun(f: (Double) => Double) = f(0.25)nfun: (f: Double => Double)Doublennscala> fun((x: Double) => 3 * x)nres16: Double = 0.75nn// 由於fun方法知道會傳入一個類型為(Double) => Double的函數,可以簡單地寫成nnscala> fun((x) => 3 * x)nres17: Double = 0.75nn// 對於只有一個參數的函數,可以省略參數外圍的()nnscala> fun(x => 3 * x)nres18: Double = 0.75nn// 如果參數在=>右側只出現一次,可以用_替換掉它nnscala> fun(3 * _)nres19: Double = 0.75n

  • 常用的高階函數

scala> (1 to 9).map(0.1 * _)nres20: scala.collection.immutable.IndexedSeq[Double] = Vector(0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9)nn/////nscala> (1 to 9).map("*" * _).foreach(println _)n*n**n***n****n*****n******n*******n********n*********nn/////nscala> (1 to 9).filter(_ % 2 == 0)nres23: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8)nn///// 相當於1 * 2 * 3 * 4 ... * 9nscala> (1 to 9).reduceLeft(_ * _)nres0: Int = 362880nn...n

閉包

  • 閉包是一個函數,返回值依賴於聲明在函數外部的一個或多個變數。
  • 閉包通常來講可以簡單的認為是可以訪問一個函數裡面局部變數的另外一個函數。

scala> def mulBy(factor: Double) = (x: Double) => factor * xnmulBy: (factor: Double)Double => Doublennscala> val triple = mulBy(3)ntriple: Double => Double = <function1>nnscala> val half = mulBy(0.5)nhalf: Double => Double = <function1>nnscala> println(triple(14) + " " + half(14))n42.0 7.0n

mulBy的首次調用將參數變數factor設置為3,該變數在(x: Double) => factor * x函數的函數體內被引用,該函數被存入triple。

接下來,mulBy再次被調用,這次factor設置為0.5,該變數在(x: Double) => factor * x函數的函數體被引用,該函數被存入half。

每一個返回的函數都有自己的factor設置,這樣一個函數被稱做閉包,閉包由代碼和代碼用到的任何非局變數定義構成。

柯里化

  • 柯里化指的是將原來接收兩個參數的函數變成新的接收一個參數的函數的過程。新的函數返回一個以原有第二個參數作為參數的函數

scala> def mul(x: Int, y: Int) = x * ynmul: (x: Int, y: Int)Intnnscala> def mulOne(x: Int) = (y: Int) => x * ynmulOne: (x: Int)Int => Intnnscala> mulOne(6)(7)nres1: Int = 42nn// mulOne(6)的結果是函數(y: Int) => 6 * y,崦這個函數又被應用到7,因此得到42。n

敬請期待下一篇<模式匹配與樣例類>~

作者:Yezhiwei

鏈接:Scala快速入門-9-高階函數

聲明:本文來源於網路,版權歸作者所有,轉載請註明,若有什麼問題,請聯繫我們,謝謝!

推薦閱讀:

Scala中的下劃線到底有多少種應用場景?
scala case class 這時候該怎麼用?
kotlin和scala兩種語言的對比?
如何評價 scala native?

TAG:Scala |