This commit is contained in:
Ilya Kantor 2014-11-16 01:40:20 +03:00
parent 962caebbb7
commit 87bf53d076
1825 changed files with 94929 additions and 0 deletions

View file

@ -0,0 +1,59 @@
# Подсказка
Чтобы `sum(1)`, а также `sum(1)(2)` можно было вызвать новыми скобками -- результатом `sum` должна быть функция.
Но эта функция также должна уметь превращаться в число. Для этого нужно дать ей соответствующий `valueOf`. А если мы хотим, чтобы и в строковом контексте она вела себя так же -- то `toString`.
# Решение
Функция, которая возвращается `sum`, должна накапливать значение при каждом вызове.
Удобнее всего хранить его в замыкании, в переменной `currentSum`. Каждый вызов прибавляет к ней очередное значение:
```js
//+ run
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` нет рекурсивного вызова.**
Вот так была бы рекурсия:
```js
function f(b) {
currentSum += b;
return f(); // <-- подвызов
}
```
А в нашем случае, мы просто возвращаем саму функцию, ничего не вызывая.
```js
function f(b) {
currentSum += b;
return f; // <-- не вызывает сама себя, а возвращает ссылку на себя
}
```
Эта `f` используется при следующем вызове, опять возвратит себя, и так сколько нужно раз. Затем, при использовании в строчном или численном контексте -- сработает `toString`, который вернет текущую сумму `currentSum`.

View file

@ -0,0 +1,17 @@
# Сумма произвольного количества скобок
[importance 2]
Напишите функцию `sum`, которая будет работать так:
```js
sum(1)(2) == 3; // 1 + 2
sum(1)(2)(3) == 6; // 1 + 2 + 3
sum(5)(-1)(2) == 6
sum(6)(-1)(-2)(-3) == 0
sum(0)(1)(2)(3)(4)(5) == 15
```
Количество скобок может быть любым.
Пример такой функции для двух аргументов -- есть в решении задачи [](/task/closure-sum).