sum(a)(b)(c).....(n)
Prompt
Implement a function sum that adds numbers by chaining function calls. Unlike mul(a)(b)(c) which has a fixed number of calls, sum should support any number of chained calls. Calling with empty parentheses () at the end signals that you're done and want the final result.
sum(1)(2)(3)(); // Returns 6
sum(5)(-1)(2)(4)(); // Returns 10Playground
Unlike mul(a)(b)(c) where you know there are exactly 3
calls, here you don't know how many calls there will be.
You need a way to keep accepting numbers until the user
signals "I'm done."
The returned function needs to check: did the caller pass a number, or did they call with empty parentheses? That check determines whether to keep going or return the total.
Think recursively. When a number is provided, you can call
sum again with the running total. When no number is
provided, just return the accumulated value.
Solution
Explanation
In mul(a)(b)(c), we always knew there were exactly 3 calls. This question is different. You could have sum(1)(2)() or sum(1)(2)(3)(4)(5)(). The chain keeps going until the caller passes empty parentheses () to say "I'm done, give me the total."
So how do we build a function that can keep accepting numbers forever until told to stop?
The solution
const sum = (num) => {
return (nextNum) => {
if (nextNum !== undefined) {
return sum(num + nextNum);
}
return num;
};
};Let's slow down and trace through sum(2)(3)() one call at a time.
Call 1: sum(2)
We call sum with 2. Inside, num is now 2. The function returns a new function and waits.
// We now have a function that remembers num = 2
// It's waiting for the next callCall 2: (3)
We call the returned function with 3. Inside, nextNum is 3. Is 3 !== undefined? Yes. So we compute num + nextNum which is 2 + 3 = 5, and call sum(5). This gives us a brand new function that remembers num = 5.
// We now have a function that remembers num = 5
// It's waiting for the next callCall 3: ()
We call the function with no arguments. Inside, nextNum is undefined (because nothing was passed). So we hit the return num line and get back 5. Done.
The key line is return sum(num + nextNum). Every time a number comes in, we add it to the running total and create a fresh sum that remembers the new total. This is what lets the chain go on for as long as needed.
Why nextNum !== undefined?
You might be tempted to write if (nextNum) instead of
if (nextNum !== undefined). But 0 is falsy in
JavaScript, so sum(5)(0)(3)() would incorrectly return
5 instead of 8. Using !== undefined properly
distinguishes "no argument was passed" from "the argument
is zero."