Вопрос проверяет понимание механизма каррирования в функциональном программировании и способов сохранения частично применённых аргументов для создания новых функций.
Каррирование — это техника в функциональном программировании, преобразующая функцию от нескольких аргументов в последовательность функций, каждая из которых принимает один аргумент. Ключевой момент — как сохраняются аргументы, переданные на промежуточных шагах.
Когда каррированная функция вызывается с аргументом, она возвращает новую функцию. Эта новая функция имеет доступ к аргументу (или аргументам), переданным на предыдущем шаге, благодаря замыканию. Замыкание — это комбинация функции и лексического окружения, в котором она была объявлена. Это окружение содержит все локальные переменные, которые были доступны на момент создания функции, включая параметры внешней функции.
Рассмотрим простую функцию сложения и её каррированную версию:
// Обычная функция
function add(a, b) {
return a + b;
}
// Каррированная версия
function curryAdd(a) {
// Аргумент 'a' сохраняется в замыкании
return function(b) {
// Внутренняя функция имеет доступ к 'a'
return a + b;
};
}
const addFive = curryAdd(5); // '5' хранится в замыкании addFive
console.log(addFive(3)); // 8
console.log(addFive(10)); // 15В этом примере значение 5 хранится в замыкании функции, которую возвращает curryAdd(5). Каждый вызов addFive использует это сохранённое значение.
На практике используют обобщённые реализации, работающие с любым количеством аргументов. Вот пример для функции с тремя аргументами:
function curry(fn) {
return function curried(...args) {
// Если переданных аргументов достаточно, вызываем исходную функцию
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
// Иначе возвращаем новую функцию, которая запомнит текущие аргументы
return function(...args2) {
// Все аргументы (старые и новые) хранятся в замыкании
return curried.apply(this, args.concat(args2));
};
}
};
}
// Использование
function sum(a, b, c) {
return a + b + c;
}
const curriedSum = curry(sum);
const addTwo = curriedSum(2); // Запоминает 2
const addTwoAndThree = addTwo(3); // Запоминает 2 и 3
console.log(addTwoAndThree(5)); // 10 (2+3+5)Здесь промежуточные аргументы накапливаются в массиве args, который сохраняется в замыкании каждой возвращаемой функции.
Итог: Каррирование использует замыкания для хранения промежуточных аргументов, что позволяет создавать гибкие и переиспользуемые функции. Применяйте его, когда нужно создавать множество похожих функций с частично заданными параметрами или строить цепочки функциональных преобразований.