You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/11-currying-partials/1-ask-currying/solution.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@
8
8
9
9
Теперь `user` берётся из внешних переменных, и всё выполняется правильно.
10
10
11
-
2. Либо сделайте из `user.login` функцию частичного применения, которая использует `user`, как контекст, и у которой установлен правильный первый аргумент:
11
+
2. Либо сделайте из `user.login` функцию частичного применения, которая использует `user` как контекст, и которой передан корректный первый аргумент:
Вызов `mul.bind(null, 2)` создаёт новую функцию `double`, которая передаёт вызов `mul`, фиксируя `null`, как контекст и `2` -- как первый аргумент. Следующие аргументы передаются "как есть".
43
+
Вызов `mul.bind(null, 2)` создаёт новую функцию `double`, которая передаёт вызов `mul`, фиксируя `null` как контекст и `2` -- как первый аргумент. Следующие аргументы передаются "как есть".
44
44
45
45
Это называется [частичное применение](https://ru.wikipedia.org/wiki/Частичное_применение) -- мы создаём новую функцию, фиксируя некоторые из существующих параметров.
Для чего мы обычно создаём функцию с частичным применением?
66
66
67
-
Польза от этого в том, что мы можем создать независимую функцию с понятным названием (`double`, `triple`). Мы можем использовать её и не передавать каждый раз первый аргумент, т.к. он зафиксирован с помощью `bind`.
67
+
Польза от этого в том, что возможно создать независимую функцию с понятным названием (`double`, `triple`). Мы можем использовать её и не передавать каждый раз первый аргумент, т.к. он зафиксирован с помощью `bind`.
68
68
69
-
В других случаях, частичное применение полезно, когда у нас есть очень общая функция и, для удобства, мы хотим создать её частный случай.
69
+
В других случаях частичное применение полезно, когда у нас есть очень общая функция и для удобства мы хотим создать её частный случай.
70
70
71
-
Например, у нас есть функция `send(from, to, text)`. Потом, внутри объекта `user`, мы можем захотеть использовать её частный случай: `sendTo(to, text)`, который отправляет текст от имени текущего пользователя.
71
+
Например, у нас есть функция `send(from, to, text)`. Потом внутри объекта `user` мы можем захотеть использовать её частный случай: `sendTo(to, text)`, который отправляет текст от имени текущего пользователя.
72
72
73
73
## Частичное применение без контекста
74
74
@@ -110,7 +110,7 @@ user.sayNow("Hello");
110
110
- Затем передаёт ей `...argsBound` -- аргументы из "частичного" вызова (`"10:00"`)
111
111
- Затем передаёт ей `...args` -- аргументы полученные обёрткой (`"Hello"`)
112
112
113
-
Итак, это не сложно сделать с помощью оператора `spread`?
113
+
Итак, это легко сделать с помощью оператора расширения?
114
114
115
115
Так же есть готовый вариант [_.partial](https://lodash.com/docs#partial) из библиотеки lodash.
116
116
@@ -122,7 +122,7 @@ user.sayNow("Hello");
122
122
123
123
Каррирование не вызывает функцию. Оно просто трансформирует её.
124
124
125
-
Давайте создадим функцию-помощник`curry(f)`, которая выполняет каррирование функции `f` с двумя аргументами. Другими словами, `curry(f)` для функции с двумя аргументами `f(a, b)` трансформирует её в `f(a)(b)`.
125
+
Давайте создадим вспомогательную функцию `curry(f)`, которая выполняет каррирование функции `f` с двумя аргументами. Другими словами, `curry(f)` для функции с двумя аргументами `f(a, b)` трансформирует её в `f(a)(b)`.
126
126
127
127
```js run
128
128
*!*
@@ -145,21 +145,21 @@ let carriedSum = curry(sum);
145
145
alert( carriedSum(1)(2) ); // 3
146
146
```
147
147
148
-
Как вы видите, имплементация -- это серия обёрток.
148
+
Как вы видите, реализация состоит из множества обёрток.
149
149
150
150
- Результат `curry(func)` -- обёртка `function(a)`.
151
151
- Когда она вызывается как `sum(1)`, аргумент сохраняется в лексическом окружении и возвращается новая обёртка `function(b)`.
152
152
- When it is called like `sum(1)`, the argument is saved in the Lexical Environment, and a new wrapper is returned `function(b)`.
153
153
- После чего `sum(1)(2)`, наконец, вызывает `function(b)`, предоставляя `2` и передаёт вызов к оригинальной функции `sum`, принимающей несколько аргументов.
154
154
155
-
Более продвинутая имплементация каррирования, как [_.curry](https://lodash.com/docs#curry) из библиотеки lodash, делает нечто более сложное. Она возвращает обёртку, которая позволяет выполнить функцию, если переданы все аргументы, в противном же случае -- возвращает функцию частичного применения.
155
+
Более продвинутая реализация каррирования, как [_.curry](https://lodash.com/docs#curry) из библиотеки lodash, делает нечто более сложное. Она возвращает обёртку, которая позволяет выполнить функцию, если переданы все аргументы, в противном же случае -- возвращает функцию частичного применения.
156
156
157
157
```js
158
158
functioncurry(f) {
159
159
returnfunction(...args) {
160
160
// if args.length == f.length (количество аргументов, принимаемое f).
161
161
// тогда передаёт вызов f
162
-
//в противном случае, возвращает функцию частичного применения, которая фиксирует первые аргументы
162
+
// в противном случае возвращает функцию частичного применения, которая фиксирует первые аргументы
163
163
};
164
164
}
165
165
```
@@ -168,7 +168,7 @@ function curry(f) {
168
168
169
169
Чтобы понять выгоду, нам определенно нужен пример из реальной жизни.
170
170
171
-
Продвинутое каррирование позволяет вызывать функцию, и нормально, и частично.
171
+
Продвинутое каррирование позволяет вызывать функцию, как обычно, так и частично.
172
172
173
173
Например, у нас есть функция логирования `log(date, importance, message)`, которая подготавливает и выводит информацию. В реальных проектах у таких функций есть много других полезных возможностей, например, посылать логи по сети:
1. Мы ничего не потеряли после каррирования: `log` всё так же можно вызывать нормально.
219
-
2. Мы смоглиол создать функции с частичным применением, как сделали для логов с текущим временем.
219
+
2. Мы смогли создать функции с частичным применением, как сделали для логов с текущим временем.
220
220
221
-
## Продвинутая имплементация каррирования
221
+
## Продвинутая реализация каррирования
222
222
223
-
В случае, если вам интересны детали (не обязательно!), вот "продвинутая" имплементация каррирования, которую мы могли бы испольовать выше.
223
+
В случае, если вам интересны детали (не обязательно!), вот "продвинутая" реализация каррирования, которую мы могли бы использовать выше.
224
224
225
225
Она очень короткая:
226
226
@@ -274,7 +274,7 @@ function curried(...args) {
274
274
Когда мы запускаем её, есть два пути:
275
275
276
276
1. Вызвать сейчас: если количество переданных аргументов `args` совпадает с количеством аргументов при объявлении функции (`func.length`) или больше, тогда вызов просто переходит к ней.
277
-
2. Частичное применение: в противном случае,`func` не вызывается сразу. Вместо этого, возвращается другая обёртка `pass`, которая снова применит `curried`, передав предыдущие аргументы вместе с новыми. Затем, при новом вызове, мы опять получим, либо новое частичное применение (если аргументов не достаточно), либо, наконец, результат.
277
+
2. Частичное применение: в противном случае `func` не вызывается сразу. Вместо этого, возвращается другая обёртка `pass`, которая снова применит `curried`, передав предыдущие аргументы вместе с новыми. Затем при новом вызове, мы опять получим, либо новое частичное применение (если аргументов не достаточно), либо, наконец, результат.
278
278
279
279
Например, давайте посмотрим, что произойдёт в случае `sum(a, b, c)`. У неё три аргумента, так что `sum.length = 3`.
280
280
@@ -295,7 +295,7 @@ function curried(...args) {
295
295
```smart header="Немного больше, чем каррирование"
296
296
По определению, каррирование должно превращать `sum(a, b, c)` в `sum(a)(b)(c)`.
297
297
298
-
Но, как было описано, большинство имплементаций каррирования в JavaScript более продвинуты: они так же оставляют вариант вызова функции с несколькими аргументами.
298
+
Но, как было описано, большинство реализаций каррирования в JavaScript более продвинуты: они также оставляют вариант вызова функции с несколькими аргументами.
299
299
```
300
300
301
301
## Итого
@@ -304,7 +304,7 @@ function curried(...args) {
304
304
305
305
Частичное применение удобно, когда мы не хотим повторять один и тот же аргумент много раз. Например, когда у нас есть функция `send(from, to)`, и `from` всё время будет одинаков для нашей задачи, мы можем выполнить частичное применение и дальше работать с ним.
306
306
307
-
-*Каррирование* -- это трансформация, которая превращает вызов `f(a, b, c)` в `f(a)(b)(c)`. В JavaScript имплементации обычно позволяют вызывать функцию обоими вариантами: либо
307
+
-*Каррирование* -- это трансформация, которая превращает вызов `f(a, b, c)` в `f(a)(b)(c)`. В JavaScript реализация обычно позволяют вызывать функцию обоими вариантами: либо
308
308
нормально, либо возвращают частичное применение, если количество аргументов недостаточно.
309
309
310
310
Каррирование подходит тогда, когда мы хотим легко использовать частичное применение. Как мы видели в примерах с логами: универсальная функция `log(date, importance, message)` после каррирования возвращает нам частичное применение, когда вызывается с одним аргументом, как `log(date)` или двумя аргументами, как `log(date, importance)`.
0 commit comments