透過 JavaScript,Ruby,PHP,C# 語言,理解 Java 的 Lambda 語法
日前 OpenJDK 發表了第一版的 Java Lambda 語法 (First Version of Java Lambda Syntax Sparks Debate),語法好壞,爭論不斷。本文分別列出了以 JavaScript, PHP, Ruby, C# 語言模仿 Java Lambda 範例的程式碼。
在數學中,lambda 有一個嚴謹的定義。但在是程式語言中,lambda 有另一個更廣泛的理解,即「匿名函數」(anonymous function)。在大多數程式語言中,根本沒有區分 lambda 與匿名函數,因此有些程式語言用 lambda 稱呼,有些程式語言用匿名函數稱呼。本文使用了五種程式語言,所以在稱呼上,會夾雜使用 lambda 與匿名函數。
Java
Java 的 lambda 語法看來怪怪的?我熟悉的程式語言還算屈指可數,兩手並用就算得出來,我看到這語法是楞了一下,這還是 Java 嗎?專精 Java 的程序員看了更是不習慣,我同事第一眼還以為這是 jQuery 。
說它怪,但其實也不太難懂。待我點撥怎麼寫,立馬就會。就以 JavaScript 為例吧。先用 JavaScript 的語法寫出來,如下所示。
JavaScript
JavaScript 不會主動將函式的最後一行結果視為回傳值,必須以 return 回傳。其他細項可參閱 The practice of anonymous recursion function in JavaScript 。
接著做三件事。第一,JavaScript 語法的 function
換成 Java lambda 語法的 #
;第二,把包著函數本體的 { }
換成 ( )
;第三,Java 是靜態型別語言,所以你必須再為參數列中的每個參數加上型態宣告。這樣就完工了。閱讀方式請反向理解。
如果你想要在定義 lambda 之後立即調用,在 JavaScript 中,我們只需要直接在定義後套用「( )運算子」 operator ( )
即可。但是 Java 並不將符號 ( )
視為運算子,你想這麼做,就要在 lambda 本體與 ( )
之間加上屬性連接符 .
,因此就出現了 #()(3).()
這種句子 。只是這樣在語法上就出現分岐了,因為這種寫法看來仿彿 .
才是「( )運算子」。按 Java 一慣的語法,至少也該在連接符之後加上一個方法名稱,例如 #()(3).call()
,讀起來也會清楚些。
在我看來,以上所述也涵蓋了 Java lambda 現行語法為人垢病之處。其實還不少,本文就列了四個。
-
新增符號
#
代表 lambda ,而不用關鍵字function
或lambda
(從JavaScript 改寫為 Java lambda 的第一個動作)。在 Java 的語言文化中,向來是不喜用特殊符號做事的;反而在 shell script 很常使用特殊符號。所以這個用法,被人批為像是 Perl 的程式碼。 -
混用
( )
與{ }
包覆 lambda 本體,而不是一貫採用表達程式碼區塊的{ }
(從JavaScript 改寫為 Java lambda 的第二個動作)。看看其他語言的 lambda 語法,Java lambda 區分成用( )
與{ }
兩種使用情境,實在是找人麻煩啊。 - lambda 的參數列清單中,要加上型態宣告(從JavaScript 改寫為 Java lambda 的第三個動作)。若參數是 int 這種原生型態還好;若是自定義的類別,往往是長長一串名稱。如 lambda 要傳兩三個參數,說不定參數列清單的字數,就比 lambda 本體的程式碼字數還多。被這麼一搞,lambda 的使用價值可就打五折了。
-
直接調用 lambda 時,還要加一個連接符
.
。具體缺點如上述,不再重複。
同樣的例子,我們再來看看其他程式語言如何寫。
PHP5.3 / PHP6
PHP5 到了 5.3版以後才增加匿名函數的語法,基本上照抄 JavaScript。細項請參閱 PHP 5.3/6 新增功能 - Closures 。此外,基於 PHP 的語法限制,它不允許你在定義後直接以 ()運算子
調用匿名函數。但是它可以直接作為其他函數的參數使用,所以我們可以用 call_user_func()
實現定義後立即調用的目的。
Ruby
Ruby 有相當靈活而強大的 closure 與 lambda 能力,與一致的表達語法。模仿本文的 Java 程式碼需要利用 Kernel.proc
實現。細項可參閱 Ruby block and Proc 。
C# 3.0
單獨使用時, C# 的 lambda 語法看來也很奇怪。但若放入 LINQ 敘述中就不同了。渾然天成,仿彿一體。MSDN 有關於 C# Lambda 語法的詳細說明,請參閱 Lambda Expressions (C# Programming Guide) @ MSDN 。
樂多舊回應