Let's explain how the `add` function works.
As I learned from my students years when we have a math problem, we have to search for clues for the solution in the given conditions.
Let's start with the first example:
add() returns 0
The function add can be called with one numeric argument or without arguments. In JavaScript, we check if an argument is given by comparing it to `undefined`.
function add(n) {
if (n === undefined) {
return 0;
}
}
add(); // => 0
Ok, it was easy.
From the second example `add(1)() = 1`, we see that `add` must return a function in order to be able to call it. let's call the returned function `adder`:
function add(n) {
if (n === undefined) {
return 0;
}
function adder(m) {
}
return adder;
}
The `adder` also takes one or zero arguments. When it is called without an argument, it must return the number given initially to `add`:
function add(n) {
if (n === undefined) {
return 0;
}
function adder(m) {
if (m === undefined) {
return n;
}
}
return adder;
}
add(7)(); // => 7
Now that example works ` add(7)() => 7 `. We called that "closure". It means that when a function ( `add` ) returns another function ( `adder` ), the returned function "remembers" the arguments from the scope of the outer function. We use that to be able to keep the current sum between the calls. So, `adder` remembers `n` and it is able to return it.
Only one thing remained - to be able to call `add` in a chain like that: `add(n1)(n2)(n3)...(nt)() => n1+n2+n3+ ... + nt;`
We use recursion for that. `adder` calls `add` with the sum of `n` and `m`.
function add(n) {
if (n === undefined) {
return 0;
}
function adder(m) {
if (m === undefined) {
return n;
}
return add(n + m);
}
return adder;
}
add(7)(0)(7)(); // => 14
It appears that when we call `add` with a number, it returns `adder` as many times as we continue giving a numeric argument. We show the result when calling without an argument and then `adder` returns the current sum equal to `n`.
So we used 'closure' and 'recursion' in that challenge to solve a task, which looks unsolvable. It is a usual example of 'closure' to use two separate functions like that:
function makeAdder(n) {
function adder(m) {
return m + n;
}
return adder;
}
const adder5 = makeAdder(5);
adder5(7); // => 12
However, this uses two separate functions, it is limited to adding only two numbers, and the second function can only add 5.
My challenge was to make it with one function, that is able to sum an arbitrary count of numbers and also to be able to be "reset". It is almost magic! I was not sure if it was possible at all.