Perl的人有一個很好的例子,說明以某種功能性的方式使用函數引用–他們稱其為Schwartzian變換(但我相信它最初是Lisp的一種技巧,有時也稱為decorate-sort-undecorate)。 由于這里只有我們JVM雞,我在Clojure中重寫了它(實際上這是本書第9章中的示例之一)。
這是Clojure代碼的片段,它定義了執行Schwartzian轉換的函數。 基本上,它提供了一種非常簡單的方法,可以根據調用者提供的輔助功能(稱為“鍵控功能”)對列表進行排序。
(defn schwarz [x f](map #(nth %1 0)(sort-by #(nth %1 1)(map #(let [w %1](list w (f w)) ) x))))
該代碼執行三個獨立的步驟-創建一個由對組成的列表(原始值與通過將鍵控函數應用于原始值而獲得的值配對),然后根據鍵控函數的值對對進行排序。 最后,通過僅從排序對對列表中的每對中獲取原始值(并丟棄鍵控函數值)來構建新列表。
在各種提議的Java語法變體中,這看起來像什么? 讓我們快速看一下每一個(請注意,由于Java的類型系統更加靜態,因此我們的許多類型聲明都有些冗長):
// Strawman, with round brackets for single-expression lambdas
public List<T> schwarz(List<T> x, Function<T, Pair<T,V extends Comparable<T>>> f) {
return map(#(T w)(makelist(w, f.apply(w))), x).sort(#(Pair<T, V extends Comparable<T>> l)(l.get(1))).map(#(Pair<T, V extends Comparable<T>> l)(l.get(0)));
}// Strawman, with braces for all lambdas
public List<T> schwarz(List<T> x, Function<T, Pair<T,V extends Comparable<T>>> f) {
return map(#(T w){makelist(w, f.apply(w))}, x).sort(#(Pair<T, V extends Comparable<T>> l){l.get(1)}).map(#(Pair<T, V extends Comparable<T>> l){l.get(0)});
}// BGGA
public List<T> schwarz(List<T> x, Function<T, Pair<T,V>> f) {
return map({T w -> makelist(w, f.apply(w))}, x).sort({Pair<T, V extends Comparable<T>> l -> l.get(1)}).map({Pair<T, V extends Comparable<T>> l -> l.get(0)});
}// SotL
public List<T> schwarz(List<T> x, Function<T, Pair<T,V>> f) {
return map(#{T w -> makelist(w, f.apply(w))}, x).sort(#{Pair<T, V extends Comparable<T>> l -> l.get(1)}).map(#{Pair<T, V extends Comparable<T>> l -> l.get(0)});
}// Redmond
public List<T> schwarz(List<T> x, Function<T, Pair<T,V extends Comparable<T>>> f) {
return map((T w) -> {makelist(w, f.apply(w))}, x).sort((Pair<T,V extends Comparable<T>> l) -> {l.get(1)}).map((Pair<T, V extends Comparable<T>> l) -> {l.get(0)});
}
如何評估它們? 我的標準是:
- 需要以一個可見的識別標記開始,以便lambda可以從周圍的代碼中脫穎而出。 #是一個方便的字符。
- 需要使用{}分隔語法。 閉包是一種塊,因此它們在代碼中應類似于塊。
- 需要全部集成在一起,因此語法具有視覺一致性,并且lambda顯示為單個單元。
- 優選地,需要具有不帶參數的函數文字的專用縮寫形式(空lambda)。
基于這些標準,對我來說,雷德蒙德是最糟糕的選擇-并且我為本書編寫Scala的經驗證明了這一點-我發現Scala的函數字面量比其他語言更難使用而沒有問題。 BGGA稍微好一點,但是我不喜歡缺少一個簡單的識別標記來告訴我“你好! 我是lambda”。
這使它始終可以在SotL和Strawman之間進行選擇。 這兩個的選擇有些隨意。 在我看來,Strawman-always-brace看起來像是一個真正的Java方法聲明,但帶有“魔術名稱”#-而SotL是真正的新語法,但更接近Redmond和BGGA樣式-因此,這可能是一個可以接受的折衷方案對于熟悉這些表格的開發人員。
綜合考慮,我的首選是:
- SotLhttp://www.blogger.com/img/blank.gif
- 稻草人總是大括號
- BGGA
- 斯特勞曼單表達輪
- 雷德蒙德
請使用注釋(在下面或在原始來源處 )告訴我們您對這個問題的看法。 當然,這不會在Java 7中出現-但是現在開始考慮Java 8和未來還為時過早。
參考: Java 7開發人員博客上的 JCG合作伙伴提供的Lambda語法替代方案 。
- 適用于Mac OS X的官方Java 7 –狀態
- 速覽Java 7 MethodHandle及其用法
- 了解和擴展Java ClassLoader
- Java內存模型–快速概述和注意事項
翻譯自: https://www.javacodegeeks.com/2011/06/java-lambda-syntax-alternatives.html