Currying a function that takes infinite arguments

后端 未结 4 1572
北恋
北恋 2020-11-30 12:01

Using ES5, how do you curry a function that takes infinite arguments.

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


        
4条回答
  •  感动是毒
    2020-11-30 12:40

    There is more generic approach by defining a curry function that takes minimum number of arguments when it evaluates the inner function. Let me use ES6 first (ES5 later), since it makes it more transparent:

    var curry = (n, f, ...a) => a.length >= n
        ? f(...a)
        : (...ia) => curry(n, f, ...[...a, ...ia]);
    

    Then define a function that sums all arguments:

    var sum = (...args) => args.reduce((a, b) => a + b);
    

    then we can curry it, telling that it should wait until at least 2 arguments:

    var add = curry(2, sum);
    

    Then it all fits into place:

    add(1, 2, 3) // returns 6
    var add1 = add(1);
    add1(2) // returns 3
    add1(2,3) // returns 6
    add1(4,5,6) // returns 16
    

    You can even skip creating add by providing the first argument(s):

    var add1 = curry(2, sum, 1);
    

    ES5 version of curry is not as pretty for the lack of ... operator:

    function curry(n, f) {
        var a = [].slice.call(arguments, 2);
        return a.length >= n
            ? f.apply(null, a)
            : function () {
                var ia = [].slice.call(arguments);
                return curry.apply(null, [n, f].concat(a).concat(ia));
            };
    }
    
    function sum() {
        return [].slice.call(arguments).reduce(function (a, b) {
            return a + b;
        });
    };
    

    The rest is the same...

    Note: If efficiency is a concern, you may not want to use slice on arguments, but copy it to a new array explicitly.

提交回复
热议问题