0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Каррирование - очень интересная техника, позволяющая сильно упростить использование частичного применения на практике. Многие путают эти понятия, но, как вы увидите далее, они обозначают совершенно разные вещи.</p>
1
<p>Каррирование - очень интересная техника, позволяющая сильно упростить использование частичного применения на практике. Многие путают эти понятия, но, как вы увидите далее, они обозначают совершенно разные вещи.</p>
2
<p>В предыдущем уроке нам приходилось писать функцию-обертку для применения.</p>
2
<p>В предыдущем уроке нам приходилось писать функцию-обертку для применения.</p>
3
<p>Eсли бы наша функция getAverageSalary была каррирована, то все было бы значительно проще. Каррирование - это процесс превращения функции от n аргументов в цепочку вложенных n-функций от одного аргумента. Соответственно, каррированная функция - это множество функций от одного аргумента.</p>
3
<p>Eсли бы наша функция getAverageSalary была каррирована, то все было бы значительно проще. Каррирование - это процесс превращения функции от n аргументов в цепочку вложенных n-функций от одного аргумента. Соответственно, каррированная функция - это множество функций от одного аргумента.</p>
4
<p>Предположим, что у нас есть функция const sum = (a, b, c) => a + b + c, которая складывает три числа. Тогда ее каррированная версия будет выглядеть так: const sum2 = a => b => c => a + b + c, а использование таким: sum2(5)(10)(-2). То же самое, разложенное по функциям:</p>
4
<p>Предположим, что у нас есть функция const sum = (a, b, c) => a + b + c, которая складывает три числа. Тогда ее каррированная версия будет выглядеть так: const sum2 = a => b => c => a + b + c, а использование таким: sum2(5)(10)(-2). То же самое, разложенное по функциям:</p>
5
<p>Посмотрите внимательно на определение a => b => c => a + b + c. Эта запись очень краткая и одновременно очень емкая. Суммарное количество функций считается очень легко, оно равно сумме всех стрелок =>. Для лучшего понимания можно добавить скобки a => (b => (c => a + b + c)). Для каждого определения функции все, что находится справа от стрелки, является ее телом, каким бы сложным оно ни было. Поначалу такая запись может помочь понять, как друг в друга вложены функции, но со временем, когда вы привыкнете к обычной записи, она будет больше мешать.</p>
5
<p>Посмотрите внимательно на определение a => b => c => a + b + c. Эта запись очень краткая и одновременно очень емкая. Суммарное количество функций считается очень легко, оно равно сумме всех стрелок =>. Для лучшего понимания можно добавить скобки a => (b => (c => a + b + c)). Для каждого определения функции все, что находится справа от стрелки, является ее телом, каким бы сложным оно ни было. Поначалу такая запись может помочь понять, как друг в друга вложены функции, но со временем, когда вы привыкнете к обычной записи, она будет больше мешать.</p>
6
<p>С другой стороны, если нам нужно каррировать существующую функцию без ее реализации, то делается это так: const sum2 = a => b => c => originalSum(a, b, c). То есть создается цепочка вложенных функций, в которой количество вложений равно количеству аргументов исходной функции и в конце которой происходит вызов оригинальной функции.</p>
6
<p>С другой стороны, если нам нужно каррировать существующую функцию без ее реализации, то делается это так: const sum2 = a => b => c => originalSum(a, b, c). То есть создается цепочка вложенных функций, в которой количество вложений равно количеству аргументов исходной функции и в конце которой происходит вызов оригинальной функции.</p>
7
<p>Разберем происходящее по шагам.</p>
7
<p>Разберем происходящее по шагам.</p>
8
<p>То же самое происходит и при таком вызове: sum(10)(3)(0), разница только в том, что вызовы происходят без создания промежуточных констант.</p>
8
<p>То же самое происходит и при таком вызове: sum(10)(3)(0), разница только в том, что вызовы происходят без создания промежуточных констант.</p>
9
<p>И задача для самоконтроля. Сколько раз нужно вызвать цепочку функций const greeting = () => () => () => () => console.log('Hey!'), чтобы дойти до конца? Обязательно попробуйте прямо сейчас выполнить это задание.</p>
9
<p>И задача для самоконтроля. Сколько раз нужно вызвать цепочку функций const greeting = () => () => () => () => console.log('Hey!'), чтобы дойти до конца? Обязательно попробуйте прямо сейчас выполнить это задание.</p>
10
<p>Теперь вернемся к нашей функции расчета зарплаты в ее каррированном виде. Представим, что теперь у нас в распоряжении две вложенных функции от одного аргумента: const getAverageSalary = job => country => /* body */:</p>
10
<p>Теперь вернемся к нашей функции расчета зарплаты в ее каррированном виде. Представим, что теперь у нас в распоряжении две вложенных функции от одного аргумента: const getAverageSalary = job => country => /* body */:</p>
11
<p>Попробуем частично применить:</p>
11
<p>Попробуем частично применить:</p>
12
<h2>Применение в реальной жизни</h2>
12
<h2>Применение в реальной жизни</h2>
13
<p>В функциональных языках, подобных haskell, вопросов об использовании каррированных функций просто не встает. Они там используются постоянно, начиная с самых азов. Это одна из причин, почему стоит учить подобные языки, даже если вы не будете писать на них программы. В императивных языках такое происходит значительно реже, но не в JS. JS по своей сути очень близок к функциональным языкам. Изначально он должен был быть написан на Scheme, языке из семейства Lisp, и функции в нем занимают центральное место. Каррирование используется в различных библиотеках и иногда является их ключевой "фичей", как, например, здесь:<a>https://github.com/substantial/updeep</a>.</p>
13
<p>В функциональных языках, подобных haskell, вопросов об использовании каррированных функций просто не встает. Они там используются постоянно, начиная с самых азов. Это одна из причин, почему стоит учить подобные языки, даже если вы не будете писать на них программы. В императивных языках такое происходит значительно реже, но не в JS. JS по своей сути очень близок к функциональным языкам. Изначально он должен был быть написан на Scheme, языке из семейства Lisp, и функции в нем занимают центральное место. Каррирование используется в различных библиотеках и иногда является их ключевой "фичей", как, например, здесь:<a>https://github.com/substantial/updeep</a>.</p>