函數柯里化

什麼是「函數柯里化」

curry 的概念:只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數javascript

先看一個簡單例子,add函數接受 2 個參數(或者多個),addX函數接受 1 個參數。 換而言之,**所謂"柯里化",就是把一個多參數的函數,轉化爲單參數函數。**將一個函數轉換爲一個新的函數html

// 非柯里化
function add(x, y) {
    return x + y;
}

add(1, 2) === 3; // true

// 柯里化
function addX(y) {
    return function(x) {
        return x + y;
    };
}

addX(2)(1) == 3; // true
複製代碼

柯里化的好處

我能想到的是:java

  • 代碼複用,減小維護成本
  • 儘量的函數化,便於閱讀

"函數式編程"是一種"編程範式"(programming paradigm),也就是如何編寫程序的方法論。git

因此,不用想太多,就是一種規範同樣的東西~ ~編程

如何實現柯里化函數 curry

先來看一個栗子(這裏藉助了ramda,請自行安裝),在下面的栗子中咱們對 add 進行了柯里化,從結果上能夠看到當參數爲 1 個時返回的是個函數,當參數爲 2 個的時候返回函數,當參數爲 3 個的時候返回函數執行結果segmentfault

var _ = require("ramda");

var add = function(a, b, c) {
    return a, b, c;
};

var curry_add = _.curry(add);

console.log(curry_add(1)); // 輸出函數
console.log(curry_add(1)(2)); // 輸出函數
console.log(curry_add(1)(2)(3)); // 輸出結果
複製代碼

根據上述的小栗子,能夠獲得,柯里化後的函數若是接受到所有參數則返回函數執行結果,不然返回一個柯里化函數app

很容易想到如下僞代碼ide

var curry = function(fn) {
    return function() {
        // 假設柯里化的函數叫 curry_fn
        // if "curry_fn接受到的參數數量等於fn接受參數的數量"
        // return "fn的執行結果"
        // else return "一個柯里化函數"
    };
};
複製代碼

上述僞代碼是否是很像遞歸?函數式編程

  • 遞歸出口:curry_fn接受到的參數數量等於fn接受參數的數量
  • 重複邏輯:return "一個柯里化函數"

因而有了如下簡單實現柯里化的代碼函數

var curry = function(fn) {
    var limit = fn.length; // fn接受的參數個數
    var params = []; // 存儲遞歸過程的全部參數,用於遞歸出口計算值

    return function _curry(...args) {
        params = params.concat(args); // 收集遞歸參數
        if (limit <= params.length) {
            // 返回函數執行結果
            return fn.apply(null, params);
        } else {
            // 返回一個柯里化函數
            return _curry;
        }
    };
};
複製代碼

參考資料

相關文章
相關標籤/搜索