Closed sgtpepper43 closed 8 years ago
I’d like @gwer’s opinion as he wrote the one on currying.
Note that I am totally up for a PR expending on the current definition, and basically summing up what you just said. :)
I made an issue instead of a PR originally because I didn't want to write so much, but now I realize I probably wrote more just to argue the case than I would have if I'd just made a PR, haha.
Haha, classic. I found your concern very insightful anyway, thank you for taking the time. Looking forward to have a more complete and explicit version of this definition soon one way or another. :)
Actually currying has been added by @mallowigi, not @gwer. My bad.
Good remark. Other programming languages (functional) have a similar behavior. Currying - is not so much a mathematical transformation as a tool for easy partial application.
Let me take some definitions from the wiki of Haskell, a language where every function is curried:
Currying is the process of transforming a function that takes multiple arguments into a function that takes just a single argument and returns another function if any arguments are still needed.
and
Partial application in Haskell involves passing less than the full number of arguments to a function that takes multiple arguments.
So based on this, currying is the act of transforming the function, and partial application is about calling the function. This is also consistent with what I learned at school and with what is written in the Wikipedia article about Currying.
Now, currying changes the original function into a sequence of functions returning functions and so on, with each function accepting only one argument. But because in languages which require function arguments to be surrounded by parentheses (which JS is one of) writing something like magic(1)(2)(3)
introduces a lot of noise, the popular JS libraries allow partial application of more than one arguments. This may or may not use currying underneath, so those two should not be confused.
For example:
function makePartiallyApplicable(fn) {
function getApplier(previousArgs) {
return function apply(...args) {
const currentArgs = [].concat(previousArgs, args);
if (currentArgs.length >= fn.length) {
return fn(...currentArgs);
} else {
return getApplier(currentArgs);
}
};
}
return getApplier([]);
}
This function returns a new function that allows partial application of an arbitrary number of arguments to fn
. However, it doesn't involve actual currying.
Let me provide another example: let's say fn
accepts two arguments, fnCurry
is a curried version of fn
, and fnPartial
allows partial application to fn
. In this situation:
fnCurry(1, 2)
returns a function that requires another argumentfnPartial(1, 2)
returns fn(1, 2)
fnCurry(1, 2)(3)
returns fn(1, 3)
fnPartial(1, 2)(3)
returns fn(1, 2)(3)
, which may throw if fn(1, 2)
is not a functionI know the difference might be almost non-existent at first glance, but it is actually big, so I hope this clears things up.
In my mind, while the implementation of it is probably a mix of currying and partial application, fn(1, 2)(3)
is just syntactic sugar for fn(1)(2)(3)
, and considering in Haskell it would be fn 1 2 3
, I think the reason curry behaves this way in all the javascript libraries is to maintain that ease of use. While this isn't meant to be a place to document various libraries, I do think including a section on how currying is commonly presented in javascript would still be beneficial.
It's still definitely easier to reason about how currying works when you can just write
const curried = a => b => c => fn(a, b, c);
if this is the place people go when they find currying in javascript code and they don't know what's going on, it'd be good to know the common syntax for using a curried function.
It seems it'd be more accurate to call curry
in lodash
and ramda
and wu
Haskell-style partial application
(ie, normal partial application, but everything is curried, so, the partial application returns a curried function). Or really just a "call this method as if this was haskell" function.
In Haskell it's still ((fn 1) 2) 3
, it's just that you don't have to use the parentheses :stuck_out_tongue: But the function signature says it all, and it's based on the original meaning of currying.
I think that pointing people to a separate definition of partial application would be the best thing to do here, what do you say?
Yeah, I think a good explanation of partial application would be good. Though there's this gray area of "auto-curried partially applied functions" that wouldn't belong in partial application (because of the currying part), and since that's what curry
is doing in lodash and what not, I think it still deserves a bit of explanation on the curry page. That's basically what's in my PR, just a small explanation of how curry behaves differently in those libraries, and how they're really using partial application for the most part.
According to lodah's docs, currying
And in Ramda
And wu
The mathematical definition (or, at least, the one on wikipedia) and the one currently in the guide is
I'm not sure how it's done in other languages, but at least in all the javascript libraries a curried function can be called with multiple arguments, whereas the mathematical definition can only be called with one at a time. This type of currying might more rightly be called
auto-currying
, but I don't really know much about the formal definition anyway, so it might just still be currying. Seeing as how this is a javascript jargon glossary, I think it would make more sense to use the definition of currying as is commonly seen in javascript, even if it's a bit more complicated to explain.