I'm learning JavaScript, and I recently came across a practice problem that asked me to construct a function that could create outputs as follows:
var threeSum= sum(3);
threeSum //3
threeSum(4) //7
threeSum(4)(3) //10
threeSum(4)(3)(7) //17
threeSum(4)(3)(7)()(2) //19
threeSum - 2 //1
threeSum + 2 //5
I assume currying is involved, and I think I have a basic grasp of how currying works in the simple form of something like
a=>b=>c=> a+b+c
but I have no notion of how I would create a curried function able to handle an indeterminate number of inputs, nor how to make it such that it could result in a variable that can act as both a value and a function.
Any insight is appreciated! I just need a push in the right direction -- at this point I don't even know what I'm looking for anymore.
The trick here is that you need to define valueOf
, which allows javascript to interpret an object (like a function) as a value:
var valueAndCallable = function(x) {
var res = function(a) { return a + x };
res.valueOf = function() { return x; };
return res;
};
var v = valueAndCallable(1)
console.log(v); // function ... -
console.log(+v); // 1 - calls .valueOf()
console.log(1 + v); // 2 - calls .valueOf()
console.log(v(3)); // 4
For currying, you just want to make res()
also return a valueAndCallable
.
As stated in the comments you can't define a variable that acts like a number and a function simultaneously.
To curry variadic functions you have to pass the arity explicitly:
const curryN = n => f => {
let next = (m, acc) => x => m > 1 ? next(m - 1, acc.concat([x])) : f(...acc, x);
return next(n, []);
};
const sum = (...args) => args.reduce((acc, x) => acc + x, 0);
sum(1, 2, 3, 4, 5); // 15
curryN(5)(sum)(1)(2)(3)(4)(5); // 15
let sum3 = curryN(3)(sum);
sum3(1)(2)(3); // 6
let sum5plusX = curryN(2)(sum)(5);
sum5plusX(6); // 11
I would recommend not to use variadic functions at all. Use Array.reduce
instead. Here's an interesting tutorial about currying. It's an in-depth topic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With