Напишите функцию sum, которая будет работать как sum(a)(b) = a+b с любым количеством скобок.
Например:
sum(1)(2) == 3 sum(5)(-1)(2) == 6 sum(6)(-1)(-2)(-3) == 0 sum(0)(1)(2)(3)(4)(5) == 15
Чтобы sum(1), а также sum(1)(2) можно было вызвать новыми скобками — результатом sum должна быть функция.
Но эта функция также должна уметь превращаться в число. Для этого нужно дать ей соответствующий valueOf. А если вы хотите чтобы и в строковом контексте она вела себя также — то toString.
Функция, которая возвращается sum, должна накапливать значение при каждом вызове.
Удобнее всего хранить его в замыкании, в переменной currentSum. Каждый вызов прибавляет к ней:
function sum(a) {
var currentSum = a;
function f(b) {
currentSum += b;
return f;
}
f.toString = function() { return currentSum; };
return f;
}
alert( sum(1)(2) ); // 3
alert( sum(5)(-1)(2) ); // 6
alert( sum(6)(-1)(-2)(-3) ); // 0
alert( sum(0)(1)(2)(3)(4)(5) ); // 15
Если внимательно присмотреться к решению - вы заметите, что функция sum срабатывает только один раз. Она возвращает функцию f.
Затем, при каждом запуске функция f добавляет параметр к сумме currentSum, хранящейся в замыкании, и возвращает сама себя.
В последней строчке f нет рекурсивного вызова. Вот так была бы рекурсия:
function f(b) {
currentSum += b;
return f(); // <-- подвызов
}
А в нашем случае, мы просто возвращаем саму функцию, ничего не вызывая.
function f(b) {
currentSum += b;
return f; // <-- не вызывает сама себя, а возвращает ссылку на себя
}
Эта f используется при следующем вызове, опять возвратит себя, и так сколько нужно раз. Затем, при использовании в строчном или численном контексте — сработает toString, который вернет текущую сумму currentSum.