This question is similar to the question posted on Does groovy call partial application ‘currying’?, but not completely the same, and the answers given there do not really satisfy me.
I would like to state right at this point, before I go any further, that currying is one of the concepts that have been hard to fully understand. I think the reason for that is the fact that there seem to be two general definitions of currying, and they don’t really mean the same thing both in theory and in application.
That being said, I think currying is a very simple concept once you decide to take only one of the two definitions and stick to it. In fact, currying should not be difficult to understand at all, but in my experience, understanding currying has been the equivalent of showing a little boy an apple and telling him that fruit is called apple, and then you go on calling that fruit an orange. The boy will never understand the simple concept of an apple because you have caused an enormous amount of confusion by calling the apple an orange.
The definition of currying that I’ve accepted as the right one is that currying is taking a function of an arbitrary arity and turning it into multiple chainable functions each of which accepts only one parameter (unary functions). In code, it would look like this:
f(1,2,3);
//becomes
f(1)(2)(3);
However, some people, including well known programmers like John Resig, explain currying as something completely different. For them, currying is no more than simple partial application. There is even a generally accepted javascript function for currying:
Function.prototype.curry = function() {
var fn = this, args = Array.prototype.slice.call(arguments);
return function() {
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments)));
};
};
This functions does not really curry anything, but rather partially applies the supplied arguments. The reason why I don’t think this function curries anything is because you can end up with a function that accepts more than one argument:
var f2 = f.curry(1); //f accepts 3 arguments f(1,2,3);
f2(2,3); // calling the resulting "curried" function.
So, my question is, have I misunderstood currying or have they?
I will leave you with this post that explains currying in javascript, but in a way in which I don’t really see any currying: https://javascriptweblog.wordpress.com/2010/04/05/curry-cooking-up-tastier-functions/
4
You are right in saying that what many (if not most) people in the JavaScript community refer to as currying does not really correspond to the term as defined in Haskell.
Then again, neither does partial application. A partial application of all arguments is a full application, but this in not happening here, because if you do this for all arguments, you will still not have applied the function, but rather created a niladic function from it (a distinction that makes no sense in Haskell).
At the bottom line, for a JavaScript programmer it’s more important to understand what other JavaScript programmers mean by “currying” or “partial application”, than what a non-JavaScript programmer use the term for.
FIY, I think the correct (and not unheard of) term here is binding. You bind the arguments of a function. In particular, you can also bind the implicit this
argument of a function.
6
I think both things are very closely related, and in the case of a two-argument function fundamentally the same really, although you could call the first thing you wrote as “complete” and the second one as “partial” currying, which would more precisely be called a special form of partial application or binding, always considering the first parameter.
In your example, f2
is f(1)
in the syntax you used above, and f2(2,3)
can be read simply as syntactic sugar(!) for f2(2)(3)
. To me, currying is not so much about the mechanics of telling your language that you want to give the arguments one after the other – that is absolutely useful, no doubt, but just a special case of binding any one argument. The importance of currying, in my eyes, is as a theoretical construct that allows you to just consider one-argument functions, because everything else can be reduced to that anyway.
9
I feel that Jon Resig’s curry
function is misnamed, and is actually a form of partial application.
Wikipedia actually has a well written section contrasting currying with partial application:
Currying and partial function application are often conflated.[10] The difference between the two is clearest for functions taking more than two arguments.
Given a function of type
f:(X × Y × Z)→N
, currying producescurry(f): X→(Y→(Z→N)))
. That is, while an evaluation of the first function might be represented asf(1, 2, 3)
, evaluation of the curried function would be represented asfcurried(1)(2)(3)
, applying each argument in turn to a single-argument function returned by the previous invocation. Note that after callingfcurried(1)
, we are left with a function that takes a single argument and returns another function, not a function that takes two arguments.
I’m going to break here because that last line is really important. Jon Resig’s version of curry
produces a function that takes two arguments, which means that it is not actually a currying function.
In contrast, partial function application refers to the process of fixing a number of arguments to a function, producing another function of smaller arity. Given the definition of above, we might fix (or ‘bind’) the first argument, producing a function of type
partial(f): (Y×Z)→N
. Evaluation of this function might be represented asfpartial(2,3)
. Note that the result of partial function application in this case is a function that takes two arguments.Intuitively, partial function application says “if you fix the first arguments of the function, you get a function of the remaining arguments”. For example, if function
div
stands for the division operationx/y
, thendiv
with the parameterx
fixed at 1 (i.e.,div 1
) is another function: the same as the functioninv
that returns the multiplicative inverse of its argument, defined byinv(y) = 1/y
.The practical motivation for partial application is that very often the functions obtained by supplying some but not all of the arguments to a function are useful; for example, many languages have a function or operator similar to
plus_one
. Partial application makes it easy to define these functions, for example by creating a function that represents the addition operator with 1 bound as its first argument.
1