Что такое каррирование в JavaScript
easy

Что такое каррирование в JavaScript

Это когда мы разбиваем функцию на несколько вложенных

Когда мы объявляем функцию, то можем передать ей аргументы — данные, которые функция будет обрабатывать. Функции без разницы, сколько аргументов получать на входе, — она справится со всеми. Но иногда программистам неудобно перечислять много переменных при вызове функции. А иногда функция становится настолько сложной, что можно запутаться, какой аргумент за что отвечает и что туда нужно передать.

Чтобы в таких ситуациях разработчикам было проще, придумали каррирование — с ним можно уменьшить количество аргументов без потери работоспособности функции.

Функция в программировании — это код внутри основной программы, у которого есть своё внутреннее имя. Если использовать имя функции как команду, то программа выполнит этот мини-код, а потом продолжит работу дальше. Это делает код проще и чище, избавляет от повторов, ускоряет разработку, тестирование и совместную работу.

Например, вы пишете игру. Каждый раз, когда игрок попадает в цель, убивает врага, делает комбо, заканчивает уровень или падает в лаву, вам нужно добавить или убавить ему очков. Это делается двумя действиями: к старым очкам добавляются новые, на экран выводится новая сумма очков. Допустим, эти действия занимают 8 строк кода.

Представим, что в игре есть 100 ситуаций, когда нужно добавить или убавить очки — для каждого типа врага, преграды, уровня и т. д. Чтобы в каждой из ста ситуаций не писать одни и те же восемь строк кода, вы упаковываете эти восемь строк в функцию. И теперь в ста местах вы пишете одну строку: например, changeScore(10) — число очков повысится на 10.Если теперь изменить, что происходит в функции changeScore(), то изменения отразятся как бы во всех ста местах, где эта функция вызывается.

Что такое каррирование

Каррирование функций — это преобразование функции с любым количеством аргументов в функцию только с одним аргументом. Это сработает, только если количество аргументов в функции ограниченное, а не бесконечное (а такое тоже может быть, например с необязательными аргументами).

На английском такое преобразование называется currying, а на русском это звучит как карринг, или каррирование. Этот приём изобрёл математик Хаскелл Карри — тот самый, в честь которого назвали язык программирования Haskell.

Проще говоря, каррирование — это когда мы берём функцию, у которой много аргументов, и превращаем всё это в функцию, у которой только один аргумент.

Каррирование в JavaScript

Возьмём простую функцию, которая перемножает три аргумента:

function multiply(a, b, c) {
return a * b * c;
}

Если мы вызовем её как multiply(2, 4, 8), то получим число 64: 2 × 4 × 8 = 64

Что такое каррирование в JavaScript

Теперь выполним каррирование. Чтобы получить функцию только с одним аргументом, сделаем так:

  1. Сделаем функцию с одним аргументом (a).
  2. Внутри этой функции сделаем вложенную функцию с аргументами (b,c).
  3. Во вложенной функции перемножим a на b × c.

В классическом каррировании мы получим три функции, каждая из которых будет с одним аргументом:

  1. Сделаем функцию с одним аргументом (a).
  2. Внутри этой функции сделаем вторую вложенную функцию с аргументом (b).
  3. Внутри этой функции сделаем третью вложенную функцию с аргументом (с).
  4. Во третьей вложенной функции перемножим a на b и на c и вернём это как результат.

Запишем это на JavaScript, используя стрелочные функции:

function multiply(a) {
    return (b) => {
        return (c) => {
            return a * b * c
        }
    }
}
multiply(2)(4)(8);
Что такое каррирование в JavaScript

Суть в том, что мы превратили multiply(1,2,3) в multiply(1)(2)(3) и получили вместо одной функции серию последовательных функций. Мы не умножаем сразу 2 на 4 на 8. Вместо этого мы сначала берём 2, умножаем на 4 и потом результат умножаем на 8.

Сейчас может показаться, что у нас как было три аргумента, так и осталось, только стало сложнее. Но это потому, что мы сделали самый наглядный учебный пример, а на практике всё интереснее.

Практика

Допустим, мы хотим, чтобы программа приветствовала пользователя по имени. Без каррирования код можно написать так:

// объявляем функцию через переменную
// в функции — два аргумента
var greet = function(greeting, name) {
  // выводим приветствие и имя
  console.log(greeting + ", " + name);
};
// запускаем функцию, указав приветствие и имя
greet("Привет", "Лена");
Что такое каррирование в JavaScript

С помощью каррирования код можно переписать так, что базовая функция будет требовать только приветствие, а имя возьмёт из вложенной функции:

// объявляем основную функцию, которая сначала отвечает за формулировку приветствия
var greetCurried = function(greeting) {
  // результат — новая функция, которая формирует приветствие, добавляя к нему имя
  // имя — это аргумент для этой вложенной функции
  return function(name) {
  	// выводим полный текст приветствия
    console.log(greeting + ", " + name);
  };
};

Теперь мы можем создать новую функцию для любого типа приветствия и передать ей имя человека:

// создаём новую переменную-функцию, в которой сразу прописываем стандартное приветствие
var greetHello = greetCurried("Здравствуй");
// запускаем каррированную функцию всего с одним аргументом, хотя изначально их было два
greetHello("Лена");

При этом у нас остаётся полный контроль над каррированной функцией — мы можем вызывать её напрямую, передав каждый из параметров в  скобках:

greetCurried("Здравствуй")("Лена");

Что такое каррирование в JavaScript

Зачем и где применяют каррирование

Каррирование позволяет разбить сложные функции со множеством аргументов на более простые функции. Код становится более компактным, его проще переиспользовать. 

Представим, что мы рассчитываем скидки для покупателей нашего магазина по такой формуле, где price — цена товара, discount — объём скидки:

function disc(price, discount) {
return price * discount
}

В этой функции два аргумента. Если процент скидки для всех покупателей одинаковый, можно каррировать функцию, оставив в ней всего один аргумент:

function disc(discount) {
return (price) => {
return price * discount;
}
}

Если мы предлагаем скидку 5%, система будет автоматически умножать стоимость товара на 0,05.

Каррирование позволяет объединять несколько простых функций в одну. Например, мы хотим, чтобы по умолчанию у нас шла скидка 5% почти для всех покупателей. Но особо лояльным клиентам мы готовы дать повышенную скидку, которую будем рассчитывать по индивидуальной формуле. Чтобы реализовать эту идею, мы будем колдовать с функцией disc(discount).

Каррирование упрощает тестирование кода, который состоит из отдельных независимых друг от друга блоков. Например, мы рассчитываем объём серии цилиндрических объектов. l — длина, w — ширина, h — высота:

function volume(l, w, h) {
return l * w * h;
}

Оказывается, что высота у всех цилиндров одинаковая, 70 см. Это позволяет нам упростить функцию volume с помощью каррирования:

function volume(h) {
    return (w) => {
        return (l) => {
            return l * w * h
        }
    }
}
// сразу упрощаем будущие вызовы, где можно указывать теперь два аргумента вместо трёх
var newVolume = volume(70);

Текст:

Елена Кочеткова

Художник:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Кирилл Климентьев

Соцсети:

Юлия Зубарева

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Вам может быть интересно
easy