Skip to main content

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.

Швидкий приклад

Звичайна функція:

javascript
function sum(a, b) { return a + b; } sum(2, 3); // 5

Після карування:

javascript
function curriedSum(a) { return function (b) { return a + b; }; } curriedSum(2)(3); // 5

Те саме зі стрілковими функціями виглядає коротше:

javascript
const curriedSum = (a) => (b) => a + b; curriedSum(2)(3); // 5

Як це працює

  • curriedSum(2) повертає нову функцію, яка «пам'ятає» значення a = 2.
  • Ця функція очікує другий аргумент b.
  • Коли ми викликаємо її з 3, повертається результат 2 + 3.

Пам'ять про перший аргумент забезпечує closure: внутрішня функція зберігає доступ до області видимості зовнішньої навіть після того, як зовнішній виклик завершився.

Навіщо потрібне карування

  1. Перевикористання частково застосованих функцій

    javascript
    const add10 = curriedSum(10); add10(5); // 15 add10(7); // 17
  2. Спрощує композицію функцій, що зручно у функціональному програмуванні: функція одного аргументу легко підставляється у ланцюжок перетворень.

  3. Підвищує читабельність і гнучкість коду, особливо в бібліотеках на кшталт Lodash або Ramda, де каровані варіанти методів є з коробки.

Одним реченням: карування це перетворення функції f(a, b, c) на f(a)(b)(c), щоб її можна було викликати по частинах і перевикористовувати часткові виклики.

Карування і часткове застосування

Ці поняття близькі, але не тотожні. Карування завжди дає ланцюжок функцій рівно з одним аргументом на кожному кроці. Часткове застосування (partial application) фіксує будь-яку кількість аргументів одразу й повертає функцію, що чекає на решту:

javascript
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, тож це про виразність, а не про швидкість.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.