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/99-js-misc/03-currying-partials/article.md
+63-53Lines changed: 63 additions & 53 deletions
Original file line number
Diff line number
Diff line change
@@ -3,21 +3,21 @@ libs:
3
3
4
4
---
5
5
6
-
# Currying
6
+
# Каррінг
7
7
8
-
[Currying](https://en.wikipedia.org/wiki/Currying)is an advanced technique of working with functions. It's used not only in JavaScript, but in other languages as well.
8
+
[Каррінг](https://en.wikipedia.org/wiki/Currying)просунута техніка для роботи з функціями. Вона використовується не лише в JavaScript, але і в інших мовах програмування.
9
9
10
-
Currying is a transformation of functions that translates a function from callable as`f(a, b, c)` into callable as `f(a)(b)(c)`.
10
+
Каррінг — це трансформація функцій таким чином, щоб вони приймали аргументи не як`f(a, b, c)`, а як `f(a)(b)(c)`.
11
11
12
-
Currying doesn't call a function. It just transforms it.
12
+
Каррінг не викликає функцію. Він просто трансформує її.
13
13
14
-
Let's see an example first, to better understand what we're talking about, and then practical applications.
14
+
Давайте спочатку подивимося на приклад, щоб краще зрозуміти, про що йде мова, а потім на практичне застосування каррінгу.
15
15
16
-
We'll create a helper function `curry(f)` that performs currying for a two-argument `f`. In other words, `curry(f)`for two-argument `f(a, b)`translates it into a function that runs as `f(a)(b)`:
16
+
Створимо допоміжну функцію `curry(f)`, яка виконує каррінг функції `f` з двома аргументами. Інакше кажучи, функція `curry(f)`трансформує `f(a, b)`в `f(a)(b)`.
17
17
18
18
```js run
19
19
*!*
20
-
functioncurry(f) { // curry(f) does the currying transform
20
+
functioncurry(f) { // curry(f) виконує каррінг
21
21
returnfunction(a) {
22
22
returnfunction(b) {
23
23
returnf(a, b);
@@ -26,7 +26,7 @@ function curry(f) { // curry(f) does the currying transform
26
26
}
27
27
*/!*
28
28
29
-
//usage
29
+
//використання
30
30
functionsum(a, b) {
31
31
return a + b;
32
32
}
@@ -36,84 +36,84 @@ let curriedSum = curry(sum);
36
36
alert( curriedSum(1)(2) ); // 3
37
37
```
38
38
39
-
As you can see, the implementation is straightforward: it's just two wrappers.
39
+
Як ви бачите, реалізація доволі проста: це дві обгортки.
40
40
41
-
-The result of `curry(func)`is a wrapper`function(a)`.
42
-
-When it is called like `curriedSum(1)`, the argument is saved in the Lexical Environment, and a new wrapper is returned`function(b)`.
43
-
-Then this wrapper is called with `2` as an argument, and it passes the call to the original`sum`.
41
+
-Результат `curry(func)`— обгортка`function(a)`.
42
+
-Коли функція викликається як `sum(1)`, аргумент зберігається в лексичному середовищі і повертається нова обгортка`function(b)`.
43
+
-Далі вже ця обгортка викликається з аргументом 2 і передає виклик до оригінальної функції`sum`.
44
44
45
-
More advanced implementations of currying, such as[_.curry](https://lodash.com/docs#curry)from lodash library, return a wrapper that allows a function to be called both normally and partially:
45
+
Більш просунуті реалізації каррінгу, як наприклад[_.curry](https://lodash.com/docs#curry)із бібліотеки lodash, повертають обгортку, яка дозволяє запустити функцію як звичайним способом, так і частково:
46
46
47
47
```js run
48
48
functionsum(a, b) {
49
49
return a + b;
50
50
}
51
51
52
-
let curriedSum =_.curry(sum); //using _.curry from lodash library
52
+
let curriedSum =_.curry(sum); //використовуємо _.curry із бібліотеки lodash
53
53
54
-
alert( curriedSum(1, 2) ); // 3, still callable normally
55
-
alert( curriedSum(1)(2) ); // 3, called partially
54
+
alert( curriedSum(1, 2) ); // 3, можна викликати як зазвичай
55
+
alert( curriedSum(1)(2) ); // 3, а можна частково
56
56
```
57
57
58
-
## Currying? What for?
58
+
## Каррінг? Навіщо?
59
59
60
-
To understand the benefits we need a worthy real-life example.
60
+
Щоб зрозуміти користь від каррінгу, нам безперечно потрібний приклад з реального життя.
61
61
62
-
For instance, we have the logging function`log(date, importance, message)` that formats and outputs the information. In real projects such functions have many useful features like sending logs over the network, here we'll just use`alert`:
62
+
Наприклад, у нас є функція логування`log(date, importance, message)`, яка форматує і виводить інформацію. У реальних проектах у таких функцій є багато корисних можливостей, наприклад, посилати інформацію по мережі, тут для простоти використаний`alert`:
Now we can easily make a convenience function for current logs:
88
+
Давайте зробимо зручну функцію для логів з поточним часом:
89
89
90
90
```js
91
-
// logNow will be the partial of log with fixed first argument
91
+
// logNow буде частковим застосуванням функції log з фіксованим першим аргументом
92
92
let logNow =log(newDate());
93
93
94
-
//use it
94
+
//використаємо її
95
95
logNow("INFO", "message"); // [HH:mm] INFO message
96
96
```
97
97
98
-
Now`logNow`is `log`with fixed first argument, in other words "partially applied function" or "partial" for short.
98
+
Тепер`logNow`- це `log`з фіксованим першим аргументом, інакше кажучи, "частково застосована" або "часткова" функція.
99
99
100
-
We can go further and make a convenience function for current debug logs:
100
+
Ми можемо піти далі і зробити зручну функцію для саме налагоджувальних логів з поточним часом:
101
101
102
102
```js
103
103
let debugNow =logNow("DEBUG");
104
104
105
105
debugNow("message"); // [HH:mm] DEBUG message
106
106
```
107
107
108
-
So:
109
-
1.We didn't lose anything after currying: `log`is still callable normally.
110
-
2.We can easily generate partial functions such as for today's logs.
108
+
Отже:
109
+
1.Ми нічого не втратили після каррінгу: `log`все так само можна викликати нормально.
110
+
2.Ми можемо легко створювати частково застосовані функції, як зробили для логів з поточним часом.
111
111
112
-
## Advanced curry implementation
112
+
## Просунута реалізація каррінгу
113
113
114
-
In case you'd like to get in to the details, here's the "advanced" curry implementation for multi-argument functions that we could use above.
114
+
У разі, якщо вам цікаві деталі, ось "просунута" реалізація каррінгу для функцій з множиною аргументів, яку ми могли б використати вище.
115
115
116
-
It's pretty short:
116
+
Вона дуже коротка:
117
117
118
118
```js
119
119
functioncurry(func) {
@@ -131,7 +131,7 @@ function curry(func) {
131
131
}
132
132
```
133
133
134
-
Usage examples:
134
+
Приклад використання:
135
135
136
136
```js
137
137
functionsum(a, b, c) {
@@ -140,17 +140,17 @@ function sum(a, b, c) {
140
140
141
141
let curriedSum =curry(sum);
142
142
143
-
alert( curriedSum(1, 2, 3) ); // 6, still callable normally
144
-
alert( curriedSum(1)(2,3) ); // 6, currying of 1st arg
145
-
alert( curriedSum(1)(2)(3) ); // 6, full currying
143
+
alert( curriedSum(1, 2, 3) ); // 6, все ще можна викликати нормально
144
+
alert( curriedSum(1)(2,3) ); // 6, каррінг першого аргументу
145
+
alert( curriedSum(1)(2)(3) ); // 6, повний каррінг
146
146
```
147
147
148
-
The new`curry`may look complicated, but it's actually easy to understand.
148
+
Нова функція`curry`виглядає складною, але насправді її легко зрозуміти.
149
149
150
-
The result of `curry(func)`call is the wrapper `curried` that looks like this:
150
+
Результат виклику `curry(func)`- це обгортка `curried`, яка виглядає так:
151
151
152
152
```js
153
-
// func is the function to transform
153
+
// func - функція, яку ми трансформуємо
154
154
functioncurried(...args) {
155
155
if (args.length>=func.length) { // (1)
156
156
returnfunc.apply(this, args);
@@ -162,27 +162,37 @@ function curried(...args) {
162
162
};
163
163
```
164
164
165
-
When we run it, there are two `if` execution branches:
165
+
Коли ми запускаємо її, є дві гілки виконання `if`:
166
166
167
-
1.If passed `args`count is the same or more than the original function has in its definition (`func.length`) , then just pass the call to it using `func.apply`.
168
-
2.Otherwise, get a partial: we don't call `func`just yet. Instead, another wrapper is returned, that will re-apply`curried` providing previous arguments together with the new ones.
167
+
1.Якщо кількість переданих `args`дорівнює або більше, ніж вказано у визначенні початковій функції `(func.length)`, то викликаємо її за допомогою `func.apply`.
168
+
2.Часткове застосування: інакше `func`не викликається відразу. Замість цього, повертається інша обгортка `pass`, яка знову застосує`curried`, передавши попередні аргументи разом з новими.
169
169
170
-
Then, if we call it, again, we'll get either a new partial (if not enough arguments) or, finally, the result.
170
+
Потім при новому виклику ми знову отримаємо або нове часткове застосування (якщо аргументів недостатньо) або, нарешті, результат.
171
171
172
-
```smart header="Fixed-length functions only"
173
-
The currying requires the function to have a fixed number of arguments.
172
+
Наприклад, давайте подивимося, що станеться у разі `sum(a, b, c)`. У неї три аргументи, так що `sum.length = 3`.
174
173
175
-
A function that uses rest parameters, such as `f(...args)`, can't be curried this way.
174
+
Для виклику `curried(1)(2)(3)`:
175
+
176
+
1. Перший виклик `curried(1)` запам’ятовує `1` у своєму лексичному середовищі і повертає обгортку `pass`.
177
+
2. Обгортка `pass` викликається з `(2)`: вона бере попередні аргументи (`1`), об’єднує їх з тим, що отримала сама `(2)` і викликає `curried(1, 2)` з усіма аргументами. Оскільки число аргументів все ще менше за `3`, `curry` повертає `pass`.
178
+
3. Обгортка `pass` викликається знову з `(3)`. Для наступного виклику `pass(3)` бере попередні аргументи `(1, 2)` і додає до них `3`, викликаючи `curried(1, 2, 3)` - нарешті 3 аргументи, і вони передаються оригінальній функції.
179
+
180
+
Якщо все ще не зрозуміло, просто розпишіть послідовність викликів на папері.
181
+
182
+
```smart header="Тільки функції з фіксованою кількістю аргументів"
183
+
Для каррінгу потрібна функція з фіксованою кількістю аргументів.
184
+
185
+
З функцію, яка використовує залишкові параметри, типу `f(...args)`, каррінгу не підлягає.
176
186
```
177
187
178
-
```smart header="A little more than currying"
179
-
By definition, currying should convert `sum(a, b, c)` into `sum(a)(b)(c)`.
188
+
```smart header="Трохи більше, ніж каррінг"
189
+
За визначенням, каррінг повинен перетворювати `sum(a, b, c)` на `sum(a)(b)(c)`.
180
190
181
-
But most implementations of currying in JavaScript are advanced, as described: they also keep the function callable in the multi-argument variant.
191
+
Але, як було описано, більшість реалізацій каррінгу в JavaScript більш просунута: вони також залишають варіант виклику функції з декількома аргументами.
182
192
```
183
193
184
-
## Summary
194
+
## Підсумки
185
195
186
-
*Currying* is a transform that makes `f(a,b,c)`callable as `f(a)(b)(c)`. JavaScript implementations usually both keep the function callable normally and return the partial if the arguments count is not enough.
196
+
*Каррінг* - це трансформація, яка перетворює виклик `f(a, b, c)`на `f(a)(b)(c)`. У JavaScript реалізація зазвичай дозволяє викликати функцію обома варіантами: або нормально, або повертає частково застосовану функцію, якщо недостатня кількість аргументів.
187
197
188
-
Currying allows us to easily get partials. As we've seen in the logging example, after currying the three argument universal function `log(date, importance, message)`gives us partials when called with one argument (like `log(date)`) or two arguments (like`log(date, importance)`).
198
+
Каррінг дозволяє легко отримувати часткові функції. Як ми бачили в прикладах з логами: універсальна функція `log(date, importance, message)`після каррінгу повертає нам частково застосовану функцію, коли викликається з одним аргументом, як `log(date)` або двома аргументами, як`log(date, importance)`.
0 commit comments