top

認識 Lambda/Closure(4)從 Scala 中借鏡

認識 Lambda/Closure(3)Python 對 Lambda/Closure 的支援?<< 前情

English

在〈認識 Lambda/Closure〉系列先前的文章中,我們使用了 JavaScript 與 Python 來示範 Lambda/Closure 為何,以及如何善用它們。就學習 Lambda/Closure 而言,這是個不錯的開始,因為 JavaScript 與 Python 都是動態語言,在這些語言中不用在意變數的型態。

然而在步入靜態語言的世界時,我們都知道編譯器需要型態訊息,以便在編譯時期檢查出各種可能的型態不符之錯誤。這點很有助益,因為可以在撰寫程式的一開始就捕捉到一些錯誤,降低因錯誤而帶來的成本負擔。不過在討論到程式碼的簡潔度時,靜態語言中冗長的型態宣告常是令人詬病的對象。

先來看看 Scala 中如何定義函式好了:

def max(m: Int, n: Int): Int = if(m > n) m else n

Scala 是靜態語言,所以必須宣告函式的參數型態為何。在這邊型態宣告似乎沒什麼大問題。嗯…來看看如何宣告匿名函式並指定給變數好了。

val max: (Int, Int) => Int = (m: Int, n: Int) => if(m > n) m else n

喔…看來語法一大垞!你必須聲明 max 的型態為 (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)

如果在 Scala 中真的得用這麼冗長的語法,你還會想用 Lambda/Closure 嗎?所幸地是,Scala 的編譯器很聰明,能夠進行型態推斷(Type inference)。它能夠從原始碼前後文推斷出型態資訊,所以實際上在宣告變數或撰寫匿名函式時,有很大的機會是不用宣告型態的。例如,實際上先前的程式碼可以重新撰寫為以下的形式:

val arr = Array(2, 5, 1, 7, 8)
bubbleSort(arr, (a, b) => a > b)

在上例中,Scala 編譯器從 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, _ > _)

在這邊不打算解釋 Scala 是如何完成這類的魔法,如果有興趣瞭解的話,可以進一步看看 Scala 學習筆記。這邊的重點在於,對於靜態語言來說,類型推斷是很重要的功能。在必須提供型態資訊的場合中,類型推斷可以讓程式碼簡潔易讀,像是在宣告變數或者是撰寫匿名函式的時候。Lambda/Closure 是個表達工具,如果沒有型態推斷,過於冗長的語法只會讓開發者望之卻步,不可能讓他們有意願採用。

在下一步文章中,就會來談談 Java 中的 Lambda/Closure。不過,實際上會先來看個 舊的提案,這有助於我們瞭解 Lambda/Closure 何以會演變為現今 JDK8 中的形態。

後續 >> 認識 Lambda/Closure(五)Java 的稻草人提案

留言

留言請先。還沒帳號註冊也可以使用FacebookGoogle+登錄留言

關於作者

目前為自由工作者,專長為技術寫作、翻譯與教育訓練。喜好研究程式語言、框架、社群,從中學習設計、典範及文化。閒暇之餘記錄所學,技術文件涵蓋 C/C++、Java、Ruby/Rails、Python、JavaScript、Haskell 等多個領域。

熱門論壇文章

熱門技術文章