在〈認識 Lambda/Closure〉系列先前的文章中,我們使用了 JavaScript 與 Python 來示範 Lambda/Closure 為何,以及如何善用它們。就學習 Lambda/Closure 而言,這是個不錯的開始,因為 JavaScript 與 Python 都是動態語言,在這些語言中不用在意變數的型態。
然而在步入靜態語言的世界時,我們都知道編譯器需要型態訊息,以便在編譯時期檢查出各種可能的型態不符之錯誤。這點很有助益,因為可以在撰寫程式的一開始就捕捉到一些錯誤,降低因錯誤而帶來的成本負擔。不過在討論到程式碼的簡潔度時,靜態語言中冗長的型態宣告常是令人詬病的對象。
先來看看 Scala 中如何定義函式好了:
def max(m: Int, n: Int): Int = if(m > n) m else nval max: (Int, Int) => Int = (m: Int, n: Int) => if(m > n) m else nmax 的型態為 (Int, Int) => Int,這專用的函式型態表示,此函式會接受兩個 Int 引數,而傳回值是 Int。在定義匿名函式本身時,也必須宣告參數的型態,像是 (m: Int, n: Int) => if(m > n) m else n。如果要定義一個可接受回呼函式的參數,也必須宣告該參數的函式型態。例如:
      def bubbleSort(arr: Array[Int], order: (Int, Int) => Boolean): Unit {
    ...
    val o: Boolean = order(a, b)
    ...
}order 參數接受一個函式,該函式會有兩個 Int 參數,並傳回 Boolean 值。以下的程式碼示範了如何呼叫 bubbleSort 函式。
      val arr: Array[Int] = Array(2, 5, 1, 7, 8)
bubbleSort(arr, (a: Int, b: Int) => a > b)val arr = Array(2, 5, 1, 7, 8)
bubbleSort(arr, (a, b) => a > b)Array(2, 5, 1, 7, 8) 的程式碼中推斷出 arr 的型態會是 Array[Int],所以你就不用作宣告了。而且,Scala 編譯器可以從 arr 推斷,匿名函式將接受的引數型態會是 Int,所以實際上你只要提供參數名稱及函式本體就可以了。事實上在 Scala 中,你還可以用更短的語法來呼叫該函式。例如:
      val arr = Array(2, 5, 1, 7, 8)
bubbleSort(arr, (_: Int) > (_: Int))val arr = Array(2, 5, 1, 7, 8)
bubbleSort(arr, _ > _)在下一步文章中,就會來談談 Java 中的 Lambda/Closure。不過,實際上會先來看個 舊的提案,這有助於我們瞭解 Lambda/Closure 何以會演變為現今 JDK8 中的形態。

