Earlier quoted context omitted.
> The mental gymnastics required to read these functions and understand how they work is not negligible, it adds up. While I agree with avoiding unnecessary complication, partial application is no more complicated than object construction, something you've presumably been doing all your life. Every time you create an object whose only initialization logic is to set some internal variables, you are effectively partial…
That's a fair point, currying is the main offender here, partial application is just making a new function. With the right name it's not harder to understand. It does add complexity because you have layers of dependencies instead of everything being in the same place. The example is always some simple math, but usually functions are doing more, and when they get changed it isn't always obvious that the things that re…
Currying vs. Partial Application (2015)
31–40 of 54 posts
Re: Currying vs. Partial Application (2015)
#32It surprises me to no end that programming languages that promote a functional style with higher order functions do not support partial application as a part of the standard library. It covers 95% of the uses of curried procedures and gives you compiler warnings if you pass too few or too many arguments. In scheme we have the cut macro that all self-respecting implementations provide which guarantees you zero runtime…
Re: Currying vs. Partial Application (2015)
#33Earlier quoted context omitted.
> The mental gymnastics required to read these functions and understand how they work is not negligible, it adds up. While I agree with avoiding unnecessary complication, partial application is no more complicated than object construction, something you've presumably been doing all your life. Every time you create an object whose only initialization logic is to set some internal variables, you are effectively partial…
That's a fair point, currying is the main offender here, partial application is just making a new function. With the right name it's not harder to understand. It does add complexity because you have layers of dependencies instead of everything being in the same place. The example is always some simple math, but usually functions are doing more, and when they get changed it isn't always obvious that the things that re…
(0) Uncurried functions are easier to pass as arguments to higher-order functions, because the author of the latter doesn't have to anticipate the arity of the former.
(1) Curried functions are easier to partially apply. This is particularly useful for collection-traversing higher-order functions (map, filter, reduce, etc.).
Furthermore, functions of three or more arguments can be “partially curried” in various ways, and the optimal choice ultimately depends on how you intend to use them.
That being said, when in doubt, I tend to go for uncurried.
Re: Currying vs. Partial Application (2015)
#34Earlier quoted context omitted.
> The mental gymnastics required to read these functions and understand how they work is not negligible, it adds up. While I agree with avoiding unnecessary complication, partial application is no more complicated than object construction, something you've presumably been doing all your life. Every time you create an object whose only initialization logic is to set some internal variables, you are effectively partial…
That's a fair point, currying is the main offender here, partial application is just making a new function. With the right name it's not harder to understand. It does add complexity because you have layers of dependencies instead of everything being in the same place. The example is always some simple math, but usually functions are doing more, and when they get changed it isn't always obvious that the things that re…
On a language like Haskell, 90% of the time you see partial application it is something like `(+1)`, or `inClass isSpace`.
That insistence on functions doing more is a very OOP thing. Functions that do too much do not compose well.
Re: Currying vs. Partial Application (2015)
#35Ok, it might be too early in the morning, but I still don't understand this. I read that post, and the post by 'raganwald that the former linked to, and I still don't see any difference between currying and partial application. And yet both posts seem to imply (without showing in any way) that the two concepts are different. How come?
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...
Here's an "improvement" which also 'extends' the currying to return values:
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___...
Re: Currying vs. Partial Application (2015)
#36This is interesting, but just because you can do something doesn't mean you should, particularly in JavaScript. As soon as I started working on a large project with a team of devs my coding style began to change dramatically. Simplicity and readability become paramount. Minimize how much a dev needs to understand about the code before they can work on it, and how long it takes them to read it. With the right coding c…
For instance while writing functional Javascript code, I never curry my methods, instead I use helper methods from functional libraries such as lodash or Ramda to curry.
Where currying is useful is in cases like this:
```javascript
//Definitions
const filterUsers = (fieldName, value, users) => //Implementation
const sortUsersBy = (fieldName, users) => //Implementation
const takeUsers = (count, users) => //Implementation
//Without currying
UserService
.getUsers()
.then(users => filterUsers('active', true, users))
.then(users => sortUsersBy('age', users))
.then(users => takeUsers(3, users));
//If these methods were curried
UserService
.getUsers()
.then(filterUsers('active', true))
.then(sortUsersBy('age'))
.then(takeUsers(3));
```
Here is a video which explains proper uses of currying (and does it very well) [1]. Here is another article if your coworker start using functional programming and you want to stop them [2].Re: Currying vs. Partial Application (2015)
#37This is interesting, but just because you can do something doesn't mean you should, particularly in JavaScript. As soon as I started working on a large project with a team of devs my coding style began to change dramatically. Simplicity and readability become paramount. Minimize how much a dev needs to understand about the code before they can work on it, and how long it takes them to read it. With the right coding c…
With all due respect, I don't think you understand the purpose of currying and partial application. In your defense, the article merely explains what currying is, but does not explain why you need it. For instance while writing functional Javascript code, I never curry my methods, instead I use helper methods from functional libraries such as lodash or Ramda to curry. Where currying is useful is in cases like this: `…
Re: Currying vs. Partial Application (2015)
#38Ok, it might be too early in the morning, but I still don't understand this. I read that post, and the post by 'raganwald that the former linked to, and I still don't see any difference between currying and partial application. And yet both posts seem to imply (without showing in any way) that the two concepts are different. How come?
Partial application is applied on call site, currying at definition. Currying: const f = x => y => x + y; const g = f(1); const sum = g(2); Partial application: const f = (x, y) => x + y; const g = _ => f(1, _); const sum = g(2); Most FP languages have nicer syntax for this.
Currying takes a multi-argument function:
const f = (x, y, z) => x + y * z;
...and converts it to a function that takes a single argument, and returns a function taking the next argument, recursively: const f_curried = x => y => z => x + y * z;
const result = f_curried(1)(2)(3)
edit: maybe you were trying to convey that, in your first example, f is already a curried function? As a whole, the first example just looks like a partial-application demonstration.Re: Currying vs. Partial Application (2015)
#39Earlier quoted context omitted.
Are you typically not binding the first parameter? Why?
It's a right curry (which I can reapply for N args). It's just personal preference, but I like to write "function templates" and then "particularize" them with a curry, from right to left. The direction is unusual but it's a personal choice and arbitrary.
Re: Currying vs. Partial Application (2015)
#40Earlier quoted context omitted.
It's a right curry (which I can reapply for N args). It's just personal preference, but I like to write "function templates" and then "particularize" them with a curry, from right to left. The direction is unusual but it's a personal choice and arbitrary.
That's a right section [1] (i.e., a partial application in the second argument). There's no such thing as a right curry. [1] https://wiki.haskell.org/Section_of_an_infix_operator
>There's no such thing as a right curry.
Haha, well there is now!