Currying with functions that take unlimited argume

2020-06-16 09:13发布

Lets say i have the following add function that takes an unlimited number of arguments.

function add () {
    var total = 0;
    var args = Array.prototype.slice.call(arguments, 0);
    for (var i=0; i<args.length; i++) {
        total += arguments[i];
    }
    return total;
}

and the following curry function.

function curryFunction(orig_func) {
    var ap = Array.prototype;
    var args = arguments;
    function fn() {
        if (arguments.length != 0) {
            ap.push.apply(fn.args, arguments);
            return fn;
        } else {
            return orig_func.apply(this, fn.args);
        }
    };
    return function() {
        fn.args = ap.slice.call( args, 1 );
        return fn.apply( this, arguments );
    };
}

I then want to do something like:

var f = curryFunction(add);
var a = f(3)(4)(3);
var b = f(10)(3);
var result1 = a(); // returns 10
var result2 = b(); // returns 13 

However i always get 13 for both a() and b() i assume is because in line

fn.args = ap.slice.call(args, 1);

the existing array [3,4,3] is overwriting with []. Can someone please provide me with a hint on how to make this work? Thanks

标签: javascript
2条回答
老娘就宠你
2楼-- · 2020-06-16 09:52

Currying a function which takes indefinitely many arguments can be implemented as follows;

Lets say we have a function called addAll() which returns the sum of all provided arguments.

var addall = (...a) => a.reduce((p,c) => p + c);

And we have a curry function which takes a function and returns curried version ad infinitum up until the returned function is called with no arguments, only when the result of all previously provided arguments will be returned. OK here is the curry function.

 var curry = f => (...a) => a.length ? curry(f.bind(f,...a))
                                     : f();

Lets see it in action;

var addAll = (...a) => a.reduce((p,c) => p + c),
     curry = f => (...a) => a.length ? curry(f.bind(f,...a)) : f(),
   curried = curry(addAll),
    result = curried(10,11)(10)(37)(10,17,42)();
console.log(result);
result = curried("a","b")("c")("d")("e","f","g")();
console.log(result);

查看更多
Emotional °昔
3楼-- · 2020-06-16 10:12

The problem is that fn is scoped to curryFunction and so is shared between a and b.

All you have to do is move the definition of fn into the anonymous return function. It's then created when you call f, and the problematic fn.args = line is only called once.

Proof: jsFiddle.

查看更多
登录 后发表回答