JavaScript 可配置函數與柯里化

有時候你可能會寫出這樣的函數:

function foo(n, flag){
    var ret = 1;
    if(flag) for(var i = 1; i <= n; i++) ret *= i;
    ret += n;
    if(flag) ret /= n;
    return ret;
}

也許情況比這個更復雜,總之你希望用一個參數來控制程序流,這相當於你有一個配置函數的需求。

爲什麼不試試柯里化呢:

function foo(flag){
    return function(n){
        var ret = 1;
        if(flag) for(var i = 1; i <= n; i++) ret *= i;
        ret += n;
        if(flag) ret /= n;
        return ret;
    };
}

foo(true)(5); // 25
foo(false)(5); // 6

這個時候你就可以簡單地取一個函數別名了:

var foo1 = foo(true);
var foo2 = foo(false);

foo1(5); // 25
foo2(5); // 6

這樣就做到了函數的配置。

相比另外一種方案:

function foo(n, flag){
    var ret = 1;
    if(flag) for(var i = 1; i <= n; i++) ret *= i;
    ret += n;
    if(flag) ret /= n;
    return ret;
}
function foo1(n) {
    return foo(true, n);
}
function foo2(n) {
    return foo(false, n);
}

最終效果是相同的,但後者沒有將函數作爲參數的做法是不符合函數式編程範式的。


上一篇博文中描述的One Line DFT也有柯里化的寫法:

// recursive DFT
recursiveDFT = (inverse) => (a) => a.length == 1 ? a : flatten(transpose(transpose(a.reduce((pre, cur, i) => pre[i & 1].push(cur) && pre, [[], []]).map(v => recursiveDFT()(v))).map((v, i) => [complex.add(v[0], complex.mul(complex.fromAngle(i * (inverse ? -2 * Math.PI / a.length : 2 * Math.PI / a.length)), v[1])), complex.minus(v[0], complex.mul(complex.fromAngle(i * (inverse ? -2 * Math.PI / a.length : 2 * Math.PI / a.length)), v[1]))]))).map(v => inverse ? complex.numMul(1 / a.length, v) : v);
DFT = recursiveDFT(false);
inverseDFT = recursiveDFT(true);

var arr = [complex(3), complex(4), complex(0), complex(0)]
var rarr = DFT(arr); 
inverseDFT(rarr); // almost equals to arr

這樣就封裝了兩個子函數,看起來比較優雅。

發佈了61 篇原創文章 · 獲贊 18 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章