Pregunta

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 ?

¿Fue útil?

Solución

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

Otros consejos

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.

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top