Currying (карування)
Currying (карування) - це процес перетворення функції, яка приймає кілька аргументів, на послідовність функцій, кожна з яких приймає тільки один аргумент. Функція f(a, b, c) перетворюється на f(a)(b)(c), щоб її можна було викликати частинами й перевикористовувати частково застосовані виклики.
Теорія
TL;DR
- Карування розбиває функцію багатьох аргументів на ланцюжок функцій одного аргументу.
sum(a, b)стаєcurriedSum(a)(b).- Працює завдяки closure: кожна повернена функція пам'ятає вже передані значення.
- Дає частково застосовані функції, які зручно перевикористовувати:
const add10 = curriedSum(10). - Спрощує композицію функцій, тому широко вживається у функціональному програмуванні.
- Підвищує читабельність і гнучкість коду, особливо в бібліотеках на кшталт Lodash чи Ramda.
Швидкий приклад
Звичайна функція:
function sum(a, b) {
return a + b;
}
sum(2, 3); // 5Після карування:
function curriedSum(a) {
return function (b) {
return a + b;
};
}
curriedSum(2)(3); // 5Те саме зі стрілковими функціями виглядає коротше:
const curriedSum = (a) => (b) => a + b;
curriedSum(2)(3); // 5Як це працює
curriedSum(2)повертає нову функцію, яка «пам'ятає» значенняa = 2.- Ця функція очікує другий аргумент
b. - Коли ми викликаємо її з
3, повертається результат2 + 3.
Пам'ять про перший аргумент забезпечує closure: внутрішня функція зберігає доступ до області видимості зовнішньої навіть після того, як зовнішній виклик завершився.
Навіщо потрібне карування
-
Перевикористання частково застосованих функцій
javascriptconst add10 = curriedSum(10); add10(5); // 15 add10(7); // 17 -
Спрощує композицію функцій, що зручно у функціональному програмуванні: функція одного аргументу легко підставляється у ланцюжок перетворень.
-
Підвищує читабельність і гнучкість коду, особливо в бібліотеках на кшталт Lodash або Ramda, де каровані варіанти методів є з коробки.
Одним реченням: карування це перетворення функції f(a, b, c) на f(a)(b)(c), щоб її можна було викликати по частинах і перевикористовувати часткові виклики.
Карування і часткове застосування
Ці поняття близькі, але не тотожні. Карування завжди дає ланцюжок функцій рівно з одним аргументом на кожному кроці. Часткове застосування (partial application) фіксує будь-яку кількість аргументів одразу й повертає функцію, що чекає на решту:
function sum(a, b, c) {
return a + b + c;
}
// partial application: fix two arguments at once
const addTo3 = sum.bind(null, 1, 2);
addTo3(3); // 6Каровану ж версію викликають по одному аргументу: curried(1)(2)(3).
Типові помилки
- Плутати карування з частковим застосуванням: карування це строго один аргумент на крок.
- Забувати, що кожен крок повертає функцію, а не значення:
curriedSum(2)це функція, іcurriedSum(2) + 3дасть беззмістовний рядок. - Губити
this, коли карують метод об'єкта: стрілкові функції берутьthisіз місця оголошення, а звичайні потребуютьbind. - Каровувати все підряд: для звичайного виклику з усіма аргументами простий
sum(a, b)читається краще. - Вважати, що карування прискорює код: воно створює додаткові функції та closure, тож це про виразність, а не про швидкість.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.