For example let's take the function add. I want to be able to call:
add(1, 2)(3, 4)
and
add(1, 2)
using same implementation. I have tried writing the add function the following way:
var add = (a, b) => {
return (c, d) => {
return a + b + c + d;
}
}
This will work fine for add(1, 2)(3, 4) but it will not work for add(1, 2). I am not sure how can I check if a function is passed arguments before returning it.
As there is no way for a function (when called) to know whether its return value will also be called like a function or not, the best you can do is to let the return value be callable and have a valueOf
method, so that it can be used directly as a number in a larger expression that expects a number:
function add(...args) {
let sum = 0;
const f = function (...args) {
for (const val of args) sum += val;
return f;
}
f.valueOf = () => sum;
return f(...args);
}
console.log(+add(1, 2)(3)(4, 5));
The "trick" here is that the +
operator forces its operand to coerce to a number, and this will implicitly call the valueOf
method of the function-object that add
evaluates to. That +
operator is just one of the many ways to get that valueOf
method called. A few more examples:
console.log("result = " + add(1, 2)(3)(4, 5));
console.log(add(1, 2)(3)(4, 5) - 0);
console.log(add(1, 2)(3)(4, 5) * 1);
console.log(Number(add(1, 2)(3)(4, 5)));