7

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/

Buzu
  • 171
  • 2

3 Answers3

7

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.

  • I see your point. However, I think f(2)(3) is a bit more than syntactic sugar because f(2) returns a function, and f(2,3) performs the operation that f(3) would. But that is a minimal difference. I like how you made the distinction between complete and partial currying. I never though of that. – Buzu Mar 17 '13 at 22:51
  • I'm not saying `f(2)(3)` is syntactic sugar, quite the opposite: `f(2,3)` is syntactic sugar for the two chained calls `f(2)(3)`. Obviously, that is not how most languages implement `f(2,3)`, but when thinking in functional style or currying in particular, they are semantically the same thing. – Christopher Creutzig Mar 18 '13 at 07:28
  • I see. I misunderstood what you were saying and got it backwards. Now that you explained it I see your point even clearer than before. – Buzu Mar 18 '13 at 08:31
  • Interesting way of looking at things, although I'm not sure it is applicable outside pure functions. – back2dos Mar 18 '13 at 15:04
  • Currying and partial application are fundamentally different notions. That said, they are quite related. Please don't say `both things are fundamentally the same really` because now you are supplying fiction as opposed to fact. – Thomas Eding Mar 18 '13 at 19:25
  • They are. But the difference between creating a function that performs partial binding for the first of two parameters (not the function returned by it, but `f.curry` in the notation above) and currying seems to me to be more of interest in the theoretical side, since it effectively is an implementation of the curried form of the function. – Christopher Creutzig Mar 18 '13 at 21:23
  • A curried function internally uses partially applied functions (or at least that is one way to implement it). Currying is the process of turning a function into a curried function. A curried function acts in a way much like the partial application of arguments to a function. Just because they accomplish the same or similar goals does not mean they are the same thing. It is important to understand the difference between the following: the currying function, the curried function, and partial application. Note that curried functions have no need for partial application. – Thomas Eding Mar 18 '13 at 21:28
  • Exactly what I said. If `f` is a function of two parameters, then `g=f.curry`, the function returning a partially bound `f`, is its curried form, and `g(x)(y)=f(x,y)`. – Christopher Creutzig Mar 18 '13 at 21:32
  • Interesting comments. I think this is worth remarking "Just because they accomplish the same or similar goals does not mean they are the same thing." In fact, I always have internal debates on situations similar to the one expressed in the question. I believe we should call everything by what it is. – Buzu Mar 18 '13 at 21:50
7

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.

back2dos
  • 29,980
  • 3
  • 73
  • 114
  • "At the bottom line, for a JavaScript programmer it's more important to understand what other JavaScript programmers mean by "currying" or "partial application", then what a non-JavaScript programmer use the term for." I think that line is a very important line to take out of this. The whole answer, actually. – Buzu Mar 17 '13 at 22:56
  • 1
    Currying and partial application are well defined mathematical terms. Just because a bunch of ignorant (or stupid... or both) people are slinging around these terms like candy does not mean they know what these actually mean. Similar to how many programmers fail to understand the distinction between `argument` and `parameter`. Simply put: Misusing a word does not mean you should emulate its improper use. – Thomas Eding Mar 18 '13 at 19:22
  • 4
    @ThomasEding: The term `function` is a well defined in mathematics. By your reasoning all JavaScript programmers are both stupid and ignorant for using it when they actually mean subroutines. Also, all human language is emulation. Simply put: The same word can refer to different concepts in different contexts. – back2dos Mar 18 '13 at 20:36
  • The flaw in your argument is that one is a keyword enforced by the language. The other is a notion lifted from elsewhere. I still don't think the masses should follow a tutorial/explanation/blog about something that its author just "learned" for the first time the night before. – Thomas Eding Mar 18 '13 at 20:37
  • 2
    @ThomasEding: I see. Then it's simply all the language designers of all languages that redefine the term `function` as subroutine, that are stupid and ignorant, right? There's a quite obvious alternative hypothesis, which seems far more likely to be true to me, but I'll leave that for you to figure out. – back2dos Mar 18 '13 at 20:41
  • @ThomasEding I agree with you to a certain degree. Specifically, I think concepts should be taught right, and a word should be used to describe one, and only one concept. However, I would not really call those people stupid. However, I do think that anyone trying to teach something should make sure to teach it right. – Buzu Mar 18 '13 at 21:46
5

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 produces curry(f): X→(Y→(Z→N))). That is, while an evaluation of the first function might be represented as f(1, 2, 3), evaluation of the curried function would be represented as fcurried(1)(2)(3), applying each argument in turn to a single-argument function returned by the previous invocation. Note that after calling fcurried(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 as fpartial(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 operation x/y, then div with the parameter x fixed at 1 (i.e., div 1) is another function: the same as the function inv that returns the multiplicative inverse of its argument, defined by inv(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.

zzzzBov
  • 5,794
  • 1
  • 27
  • 28
  • 1
    I've also been thinking that since I understood the concept of currying. There are other functions out there similar to Resig's. Dustin Diaz has one very similar. The post that helped me understand currying was http://www.2ality.com/2011/09/currying-vs-part-eval.html – Buzu Mar 18 '13 at 21:54