MediumDEShaw

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 10

Playground

Hint 1

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."

Hint 2

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.

Hint 3

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 call

Call 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 call

Call 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."