Как написать функцию каррирования с использованием замыкания для суммирования аргументов до вызова без аргументов?
Что проверяют
Понимаете ли вы замыкание как способ хранить состояние между вызовами и умеете ли вернуть функцию из функции. Следом обычно просят сделать так, чтобы ветки одной цепочки не мешали друг другу, или обобщить решение на произвольную операцию.
Как отвечать
Каркас: функция возвращает другую функцию, которая либо копит аргументы, либо на пустом вызове отдаёт результат. Признак конца это args.length === 0:
function sum(...first) {
const total = first.reduce((a, b) => a + b, 0);
return function next(...args) {
if (args.length === 0) return total;
return sum(total, ...args);
};
}
sum(1)(2, 3)(4)(); // 10Что проговорить:
- где замыкание:
nextвидитtotalиз вызоваsum, хотя самаsumуже вернула управление; - почему без мутации: каждый шаг создаёт новое замыкание со своим
total. Если держать одну переменную и дописывать в неё, тоconst a = sum(1); a(2)(); a(3)();вернёт 3, а затем 6 вместо 4: ветки портят общее состояние; - остаточные параметры:
...argsпозволяют передать несколько чисел за раз,sum(1, 2)(3)(); - обобщение: вынести операцию и начальное значение в параметры, например своя
curryReduce((a, b) => a * b, 1); - отличие от классического каррирования: обычный
curry(fn)собирает ровноfn.lengthаргументов и вызывает функцию сам, без пустого вызова.
Где спотыкаются
Переопределяют valueOf или toString и выдают это за решение. Пустой вызов тогда возвращает функцию, а число появляется только при приведении типа, например +sum(1)(2)(). Условие задачи не выполнено, и console.log покажет функцию.
Проверяют if (!arg) вместо длины аргументов. Вызов sum(1)(0)() оборвётся на нуле и отдаст результат раньше времени.
Держат сумму в переменной модуля или внешней области видимости. Второй независимый вызов sum(5)() вернёт то, что накопила первая цепочка.