Function.prototype.curryCall()

Brendan Eich brendan at mozilla.org
Tue Aug 28 15:21:30 PDT 2007


That's partial application, not currying. No one has proposed its  
standardization; lots of Ajax libraries implement it much as you show  
below. The ones I've looked at play their own custom variations on a  
theme, so wouldn't all be subsumed by a standard.

/be

On Aug 28, 2007, at 2:20 PM, Peter Michaux wrote:

> Hi,
>
> Has JavaScript support for function currying been proposed? Maybe
> there is already something like this planned?
>
>
> Function.prototype.curryCall = function(scope) {
>       var args = [];
>       for (var i=1; i<arguments.length; i++) {
>           args.push(arguments[i]);
>       }
>       var f = this;
>       return function() {
>           for (var i=0; i<arguments.length; i++) {
>              args.push(arguments[i]);
>            }
>           return f.apply(scope, args);
>       }
> }
>
>
> //------------
> // Example use
>
> function foo(a, b, c, d) {
>    alert(this.name + a + b + c + d);
> }
>
> var bert = {name:'Bert'};
>
> var curriedFoo = foo.curryCall(bert, 1, 2);
>
> curriedFoo(3, 4); // alert says "Bert1234"
>
>
>
>
> Currying is handy when attaching event handlers in a for loop since
> for loops don't introduce a new scope with each iteration.
>
> Suppose we want to attach a click handler to each item in an HTML
> list. The handler prints the position of the item in the list and also
> the innerHTML of the item. One way we could write this handler...
>
> function handler(i) {
>   alert('item ' + i + ': ' + this.innerHTML);
> }
>
> var items = document.getElementById('myList').getElementsByTagName 
> ('li');
>
> // three ways to attach the handlers
>
> //----------------------------------------
> // OPTION 1:  inline currying (what a mess)
>
> for (var i=0; i<items.length; i++) {
>   var item = items[i];
>   item.addEventListener('click', (function(item, i) {
>      return function(){
>              return handler.call(item, i);
>             }
>   })(item, i), false);
> }
>
>
> //----------------------------------------------
> // OPTION 2: extracted currying (a little nicer)
>
> function curryHandler(item, i) {
>     return function() {
>       return handler.call(item, i);
>     };
> }
>
> for (var i=0; i<items.length; i++) {
>   var item = items[i];
>   item.addEventListener('click', curryHandler(item, i), false);
> }
>
>
> //--------------------------------------------------------
> // OPTION 3: with Function.prototype.curryCall (succinct!)
>
> for (var i=0; i<items.length; i++) {
>   var item = items[i];
>   item.addEventListener('click', handler.curryCall(item, i), false);
> }
>
> The event object will be passed as the second argument to the  
> handler function.
>
> There is precedence for other developers wanting this functionality. I
> believe Prototype's Function.prototype.bind() may be the same thing as
> the Function.prototype.curryCall() that I've written. The Prototype
> Function.prototype.bindEventListener() will pass the event object as
> the first argument to the curried function.
>
> Any thoughts on the utility of currying as part of JavaScript?
>
> Peter
> _______________________________________________
> Es4-discuss mailing list
> Es4-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es4-discuss




More information about the Es4-discuss mailing list