3 ms·
Partial application introduces one new closure, to capture some arguments now and allow the rest to be supplied later: f = function (x, y, z) { return [x,
by chriswarbo 9y ago
Partial application introduces one new closure, to capture some arguments now and allow the rest to be supplied later:
f = function (x, y, z) { return [x, y, z]; };
g = partiallyApply(f, 1, 2);
With these definitions (and some suitable definition of `partialApply`):
g(3) == f(1, 2, 3) == [1, 2, 3]
Note that `g` is a closure: a function with (references to) some values: the function `f`, and the data `x = 1` and `y = 2`. This closure will accept some argument (`z`) and return `f(x, y, z)`.
Whilst currying is similar, it's like partially-applying everything, and doing so implicitly. For example, given `h = curry(f)` we get a new function: a closure with a reference to `f`.
If we say `i = h(1)`, we get a new closure which references `f` and `x = 1`. We can say `j = i(2)` to get another new closure which references `f`, `x = 1` and `y = 2`. All of the following hold:
j(3) == i(2, 3) == h(1, 2, 3) == f(1, 2, 3) == [1, 2, 3]
The important thing to notice is that in the case of partial-application, we only got one extra closure, and that happened when we explicitly called the `partialApply` function.
In the case of currying, we only called the `curry` function once, to get `h`. Yet we subsequently get more and more closures, without any extra calls to the `curry` function: `h` can return new closures, and those closures can return new closures (like `i` and `j`) and so on.
In a language with strict (call by value) semantics like Javascript, this makes it hard to know when the "real" function (in our case `f`) will actually get called. This is important if `f` has side-effects, or involves some heavy computation. It also makes it harder to know when values will be garbage collected, due to the references inside these closures.
In the case of `partialApply`, only one closure is created, we know exactly where (at the point where `partialApply` is called), we know exactly what references will be captured (the arguments to `partialApply`) and we know exactly when the "real" function will get called (it will be called whenever the resulting closure is called).
To add to all of the other references in this thread, I also wrote my own a few years ago :)
Here's a basic implementation of currying in Javascript:
http://chriswarbo.net/blog/2012-02-20-currying_in_javascript.html http://chriswarbo.net/blog/2012-02-20-currying_in_javascript...
Here's an "improvement" which also 'extends' the currying to return values:
http://chriswarbo.net/blog/2012-10-01-better_currying_in_javascript.html http://chriswarbo.net/blog/2012-10-01-better_currying_in_jav...
For example, if we have the following:
a = curry(function(w, x) {
return function(y) {
return function(z) {
return w + x + y + z;
};
};
});
The "basic" version of `curry`, which is what I've seen most tutorials use, handles situations with "too few" arguments, by returning a closure:
a(1)(2)(3)(4) == a(1, 2)(3)(4) == 1 + 2 + 3 + 4
In the "improved" version we also handle situations with "too many" arguments, by passing them as arguments to the return value (of course, this assumes we're returning functions, like above); which makes all of the following equivalent:
a(1)(2)(3)(4) == a(1, 2)(3)(4)
== a(1)(2, 3)(4)
== a(1)(2)(3, 4)
== a(1, 2, 3)(4)
== a(1)(2, 3, 4)
== a(1, 2, 3, 4)
== 1 + 2 + 3 + 4
I've also written an equivalent for PHP, which goes more into the difference between partial application and currying:
http://chriswarbo.net/blog/2014-02-21-partial_application___currying_in_php.html http://chriswarbo.net/blog/2014-02-21-partial_application___...