JAVA 8函數語言程式設計(三):柯里化與惰性求值
阿新 • • 發佈:2019-01-22
百度百科裡是這麼定義柯里化的:
在電腦科學中,柯里化(Currying)是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數且返回結果的新函式的技術。
有沒有看了跟沒看一樣,那就對了,很多技術概念就是這樣,原本簡單的東西一包裝,創造個非常洋氣的馬甲,再加上一通雲裡霧裡的解釋,最後就成了高大上的高科技。
照我的理解,柯里化主要做到了以下的三點:
1. 引數數量的變化;
2. 返回了一個新的函式;
3. 惰性求值(只有需要結果的那一刻才進行求值);
對JAVA而言,雖然也支援可變引數,但骨子裡還是以陣列的方式進行支援,所以應用場景並不多,跟Javascript相比,方法對於引數的處理,還是較弱。
下面看程式碼實現:
/**
* 定義柯里化函式
* 關鍵在於接收的引數也是函式
*/
public static IntFunction<Integer> curring(Function<List<Integer>, Integer> fn) {
// 用於儲存結果
final List<Integer> result = new ArrayList<>();
// 直接返回lambda表示式,非常酷的寫法
// 依賴於JAVA超強的型別推導
return arg -> {
// 由於介面的限制,無法傳空引數
// 當傳入的值為最大值時,就立刻求值
if(arg != Integer.MAX_VALUE) {
result.add(arg);
} else {
// 好像有點JS的感覺
return fn.apply(result);
}
return null;
};
}
再看對柯里化函式的應用:
// 定義可直接呼叫的函式
IntFunction<Integer> currPrice = curring(items ->
// 匹配IntFunction的定義,將Long轉換為int
Long.valueOf(items.stream()
.mapToLong(i -> Long.valueOf(i))
.sum())
.intValue());
最後時測試程式碼:
currPrice.apply(1);
currPrice.apply(2);
currPrice.apply(3);
currPrice.apply(4);
// 最後統一求值
int result = currPrice.apply(Integer.MAX_VALUE);
assertThat(result, IsEqual.equalTo(10))
結論
越來越喜歡Java 8的lambda表示式,只需寥寥數語就可完成非常複雜的操作,再配合JAVA超強的型別推導,無論是作為函式的引數、變數還是返回值,都表現得遊刃有餘。