26

I'm trying to understand the difference between curry vs bind.

The implementation of bind is :

/*1*/   Function.prototype.bind = function ()
/*2*/   {
/*3*/        var fn = this,
/*4*/           args = Array.prototype.slice.call(arguments);
/*5*/       var object = args.shift();
/*6*/       return function ()
/*7*/       {
/*8*/           return fn.apply(object, 
/*9*/                           args.concat(Array.prototype.slice.call(arguments)))
/*10*/       };
/*11*/   }

The implementation of curry is :

/*1*/   Function.prototype.curry = function ()
/*2*/   {
/*3*/       var fn = this,
/*4*/           args = Array.prototype.slice.call(arguments);
/*5*/       return function ()
/*6*/       {
/*7*/           return fn.apply(this, 
/*8*/                           args.concat(Array.prototype.slice.call(arguments)));
/*9*/       };
/*10*/   };

I already know that curry is not an internal function (unlike bind which is in IE9+). But still:

Why do I hear people keep talking about curry , While they can simply use bind operation ?

The only difference is the context which is actually found only at the bind function.

differences

enter image description here

Example :

Let's say I have this function :

function add(x,y,z)
{
  return x+y+z;
}

I could do it with curry :

alert(add.curry(2).curry(1)(4)) //7

But I could also do it with :

alert(add.bind(undefined,2).bind(undefined,1)(4)) //7

I don't understand why this curry term function exists while it is possible to add a dummy context to the bind function.

What am I missing ?

hakre
  • 193,403
  • 52
  • 435
  • 836
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • 5
    As far as I can tell, on Chrome Version 33.0.1750.117 m, `curry` does not exist. Googling `Javascript curry` turns up no results for browsers offering it as an extension. Where is this function coming from? Are you using an external library? – user2357112 Mar 02 '14 at 13:32
  • @user2357112 I didnt say it's suppose to be in browser – Royi Namir Mar 02 '14 at 13:35
  • 3
    Then where are you running this? You don't mention node.js or any other particular environment. (node.js doesn't seem to have a `curry` method either.) – user2357112 Mar 02 '14 at 13:36
  • @user2357112 there are many discussions about curry/partial in javascript arena. Im just asking why we need curry if we could easily do it via bind. that's all – Royi Namir Mar 02 '14 at 13:39
  • 2
    I don't understand your question. `bind` is used to bind functions to contexts and `curry` to create partially applied functions. They have a different usage and the simple fact that you can use `bind` with `undefined` for currying doesn't mean that you should, because you're obfuscating your code. – Paolo Moretti Mar 02 '14 at 13:51
  • 1
    You're questioning why the term "curry" exists simply because JavaScript has a `.bind()` function? I really don't understand what you're getting at. Many functional programming concepts existed before JS had `.bind()`, and in fact before JS existed. Should they now cease to exist? – cookie monster Mar 02 '14 at 13:59
  • @cookiemonster Well , That's an answer too. While I was reading john resigs book , I found the terms bind/curry/partial and I just asked why did he want to show the curry implementation while bind is already there. ( he mentioned bind and after 2 paragraph , he mentioned curry) that's all. – Royi Namir Mar 02 '14 at 14:04
  • 3
    If you're more generally wondering about the origins of the terms, and why JS's method is called `.bind()` instead of `curry()`, I would guess that it's because `.bind()` does give you the option to bind the `this` value, which doesn't really have anything to with currying. I believe that was the main purpose of `.bind()`, since the `this` value changes so dynamically, and can be a pain to deal with in callback functions. I think the idea of `.bind()` may have come from the `prototypejs` library, but I'm not totally sure about that. – cookie monster Mar 02 '14 at 14:08

3 Answers3

23

There is a difference in intention.

Currying is to reduce the number of arguments, usually to avoid calling a function a lot with the same initial arguments. For example:

var celsiusToKelvin = add.curry(273.15);

bind() is to make sure that a function is attached to an object. It also happens to offer a currying facility, so yes you can use bind() to curry(), but if you want to curry, curry() has fewer arguments and shows your intention.

James
  • 5,635
  • 2
  • 33
  • 44
  • 1
    I agree it is about intention. To put it another way, `bind` *closes* the function, while `curry` leaves it open. Of course, as the OP observes, the operations are practically identical, and you can close a function with `curry` by binding all of its arguments. But the general assumption is that a curried function will not be invoked by itself, whereas a bound function will. – harpo Mar 02 '14 at 16:16
23

bind forces you to attach a context to the function, while by using curry, you can delay the specification of function context until invoking the curried function, useful in many cases.
consider the following example (not the perfect one, just to illustrate the idea):

function Query(sessionKey, dataBuilder) {
  this.sessionKey = sessionKey;
  this.url = "http://www.example.com/search";
  this.dataBuilder = dataBuilder
  this.search = function (term) {
    $.ajax({
      type: "POST",
      url: this.url,
      data: this.dataBuilder(term);
    })
  }
}

function dataBuilder(entity, query) {
  var payload = JSON.stringify({
    'entity': entity,
    'searchTerm': query
    'session': this.sessionKey // will be always undefined if bind(undefined,...) is used
  });
  return payload
}
var bindEx= dataBuilder.bind(undefined, "username");
var curryEx= dataBuilder.curry("username");

var usernameQuery = new Query("id1234",bindEx); // won't work, this.sessionKey will be undefined
usernameQuery = new Query("id1234",curryEx); // will  work, this.sessionKey will be id1234 in the DataBuilder
Amine Hajyoussef
  • 4,381
  • 3
  • 22
  • 26
2

I'd think it has something to do with compatibility with older browsers as bind is only available since ECMAScript 5.

See this for a list of .bind() support: http://kangax.github.io/es5-compat-table/

Also from what I've heard, most people still use curry because it looks cleaner as it doesn't need that extra undefined in the arguments.

martskins
  • 2,920
  • 4
  • 26
  • 52
  • Implementations of curry can also include both syntax sugar (no curriedFunc(3,4)(2), just curriedFunc(3,4,2) ) and also options to close the function to a set number of arguments (what was originally defined or an arbitrary number set at curry definition time). – Dtipson Jan 23 '15 at 20:23