Skip to content

Commit 6113f33

Browse files
authored
Merge pull request #2422 from lapstjup/patch-1
Update currying function to use bind instead of wrapper pass
2 parents 12b23c7 + 997f392 commit 6113f33

File tree

1 file changed

+6
-14
lines changed

1 file changed

+6
-14
lines changed

1-js/99-js-misc/03-currying-partials/article.md

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,7 @@ function curry(func) {
121121
return function curried(...args) {
122122
if (args.length >= func.length) {
123123
return func.apply(this, args);
124-
} else {
125-
return function(...args2) {
126-
return curried.apply(this, args.concat(args2));
127-
}
128-
}
124+
} else return curried.bind(this, ...args);
129125
};
130126

131127
}
@@ -154,26 +150,22 @@ The result of `curry(func)` call is the wrapper `curried` that looks like this:
154150
function curried(...args) {
155151
if (args.length >= func.length) { // (1)
156152
return func.apply(this, args);
157-
} else {
158-
return function pass(...args2) { // (2)
159-
return curried.apply(this, args.concat(args2));
160-
}
161-
}
153+
} else return curried.bind(this, ...args); // (2)
162154
};
163155
```
164156

165157
When we run it, there are two `if` execution branches:
166158

167159
1. Call now: if passed `args` count is the same as the original function has in its definition (`func.length`) or longer, then just pass the call to it.
168-
2. Get a partial: otherwise, `func` is not called yet. Instead, another wrapper `pass` is returned, that will re-apply `curried` providing previous arguments together with the new ones. Then on a new call, again, we'll get either a new partial (if not enough arguments) or, finally, the result.
160+
2. Get a partial: otherwise, `func` is not called yet. Instead, a new bounded function using curried is returned, that takes the `...args` i.e. the current arguments as pre-specified. Then on a new call, again, we'll get either a new partial (if not enough arguments) or, finally, the result.
169161

170162
For instance, let's see what happens in the case of `sum(a, b, c)`. Three arguments, so `sum.length = 3`.
171163

172164
For the call `curried(1)(2)(3)`:
173165

174-
1. The first call `curried(1)` remembers `1` in its Lexical Environment, and returns a wrapper `pass`.
175-
2. The wrapper `pass` is called with `(2)`: it takes previous args (`1`), concatenates them with what it got `(2)` and calls `curried(1, 2)` with them together. As the argument count is still less than 3, `curry` returns `pass`.
176-
3. The wrapper `pass` is called again with `(3)`, for the next call `pass(3)` takes previous args (`1`, `2`) and adds `3` to them, making the call `curried(1, 2, 3)` -- there are `3` arguments at last, they are given to the original function.
166+
1. The first call `curried(1)` returns a new bounded `curried` with `1` as pre-specified argument.
167+
2. The bounded `curried` is called with `(2)`: it takes previous args (`1`) due to bind, and new leading argument `(2)` and calls `curried(2)`. As the argument count is still less than 3, `curry` returns new bounded `curried` with (`1`, `2`) as pre-specified arguments.
168+
3. The bounded `curried` is called again with `(3)`, for the next call `curried(3)` takes previous args (`1`, `2`) and new leading argument `3`, making the call `curried(3)` -- there are `3` arguments at last, they are given to the original function.
177169

178170
If that's still not obvious, just trace the calls sequence in your mind or on paper.
179171

0 commit comments

Comments
 (0)