Computing with functions that take unlimited arguments

Suppose 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 next 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 ); }; } 

Then I 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 () and b (), I assume in the line

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

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

+7
javascript
source share
2 answers

The problem is that fn bound to curryFunction and is split between a and b .

All you have to do is move the definition of fn to an anonymous return function. Then it is created when you call f , and the problem string fn.args = is called only once.

Proof: jsFiddle .

+5
source share

The calculation of a function that takes an indefinite number of arguments can be implemented as follows:

Suppose we have a function called addAll() that returns the sum of all the arguments provided.

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

And we have a curry function that takes a function and returns an unchanged version ad infinitum until the returned function is called without arguments, only when the result of all the previously provided arguments is returned. OK here is the curry function.

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

Lets see him 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); 
+1
source share

All Articles