函数式编程-柯里化(currying)

何为柯里化

概念:在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的

参数且返回结果是新函数的技术。

上栗子

var add = function(x) {
    return function(y) {
        return x + y;
    }
}

var increment = add(1);
var addTen = add(10);

increment(2);
// 3

addTen(2);
// 12

解释:我们定义了一个add函数,这个函数接受一个参数并返回一个新的函数。调用add之后,返回的函数通过闭包可以访问到add的第一个参数。这样可以使这类函数的定义和调用更加容易。

进阶(for our enjoyment)

var curry = require('lodash').curry;
var match = curry(function(what, str) {
    return str.match(what);
})

var replace = curry(function(what, replacement, str) {
    return str.replace(what, replacement);
})

var filter = curry(function(f, array){
    return array.filter(f);
})

match(/s+/g, 'hello world');
// [' ']

match(/s+/g)('hello world');
//[' ']

var hasSpaces = match(/s+/g);
// function(x) { return x.match(/\s+/g) }

hasSpaces('hello world');
//[' ']

hasSpaces('sssss');
// null

var noVowels = replace(/[aeiou]/ig);
// function(replacement, x) { return x.replace(/[aeiou]/ig, replacement) }

var censored = noVowels("*");
// function(x) { return x.replace(/[aeiou]/ig, "*") }

censored("Chocolate Rain");
// 'Ch*c*l*t* R**n'

filter(hasSpaces, ["tori_spelling", "tori amos"]);
// ["tori amos"]

var findSpaces = filter(hasSpaces);
// function(xs) { return xs.filter(function(x) { return x.match(/\s+/g) }) }

findSpaces(["tori_spelling", "tori amos"]);
// ["tori amos"]

这里表明的是一种“预加载”函数的能力,通过传递一到两个参数调用函数,就能得到一个记住了这些参数的新函数。

当我们谈论纯函数的时候,我们常说函数接受一个输入返回一个输出。currying函数所做的正是这样:每传递一个参数调用函数,就返回一个新函数处理剩余的参数。

柯里化的好处

通过简单地传递几个参数,就能动态创建实用的新函数;而且还能带来一个额外好处,那就是保留了函数定义,尽管参数不止一个

如何实现柯里化

var add = function(){
    var sum = 0;
    for(var i = 0, l = arguments.length; i < l; i++){
        sum += arguments[i];
    }
    return sum;
}

var curry = (function(fn){
    var args = [];
    return function(){
        if(arguments.length == 0) {
            return fn.apply(this, args)
        } else {
            [].push.apply(args, arguments);
            return arguments.callee;
        }
    }
})

currySum = curry(add);

currySum(1, 2, 3);
currySum(1);
currySum(1);
currySum(1);
currySum(1);
currySum();
// 10

相关推荐