1. 程式人生 > >JAVA 8函數語言程式設計(三):柯里化與惰性求值

JAVA 8函數語言程式設計(三):柯里化與惰性求值

百度百科裡是這麼定義柯里化的:

在電腦科學中,柯里化(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超強的型別推導,無論是作為函式的引數、變數還是返回值,都表現得遊刃有餘。