问题
Is there a away to create a sum function that works with both recursive call (e.g (1)(2)(3)(4)), and multiple arguments (e.g (1, 2, 3, 4))?
Like this:
sum(5, 5) // 10
sum(5)(5) // 10
Thank you.
回答1:
You could return a function for next arguments and implement a toString method.
function sum() {
var add = function (a, b) { return a + b; },
value = Array.prototype.reduce.call(arguments, add, 0);
function f() {
value = Array.prototype.reduce.call(arguments, add, value);
return f;
};
f.toString = function () { return value; };
return f;
}
console.log(sum(5, 5));
console.log(sum(5)(5));
console.log(sum(3, 4, 5)(6, 7));
回答2:
In functional programming, what you are asking for is based on the concept of currying. Currying allows a function which takes indefinite number of parameters to be applied partially. Which means, once curried, it takes an argument stores the argument and the operation and returns another function for you to feed with the next argument.
In some languages like Haskell this is the natural behavior of all functions but not in JS. However since JS is a "sort of" functional language, which allows you to pass and return functions, currying is still quite achievable JS.
OK lets see how to curry a multi argument function generically;
function sum(n,m,o,p){ // uncurried standard function
return n + m + o + p;
}
function curry(fn){ // takes an uncurried function and returns a curried function
return function(...a){
return a.length >= fn.length ? fn(...a)
: curry(fn.bind(fn,...a));
};
}
var csum = curry(sum); // now csum is the curried version of sum
console.log(csum(1,2,3,4)); // <- 10
console.log(csum(1)(2,3,4)); // <- 10
console.log(csum(1,2)(3,4)); // <- 10
console.log(csum(1,2,3)(4)); // <- 10
console.log(csum(1)(2)(3,4)); // <- 10
console.log(csum(1)(2)(3)(4)); // <- 10
回答3:
Reference: https://codeburst.io/perpetual-currying-in-javascript-5ae1c749adc5
Thanks to Param Singh, Who came up with a good solution for infinite variadic currying problem
function callFun(fn){
const doTo = (args) => args.reduce((acc, a) => fn.call(fn, acc, a))
const next =(...args)=>{
return (...innerArg)=> {
if(innerArg.length){
return next(...args, doTo(innerArg))
}else{
return doTo(args)
}
}
}
return next()
}
const sum = callFun((a,b) => a + b)
console.log(sum(1)(2)(3,2,1)())
来源:https://stackoverflow.com/questions/45643260/sum-function-work-with-recursion-and-multiple-arguments