Skip to content

Instantly share code, notes, and snippets.

@liammclennan
Created September 6, 2012 10:48
Show Gist options
  • Save liammclennan/3654718 to your computer and use it in GitHub Desktop.
Save liammclennan/3654718 to your computer and use it in GitHub Desktop.
CoffeeScript Currying

This is a function that does some currying:

add = (a,b) ->
  if not b?
    return (c) ->
      c + a
  a + b

JavaScript provides the capability to reflect on the number of arguments:

add.length

and to determine how many arguments were provided:

add = (a,b) ->
  if arguments.length < add.length
    return (c) ->
      c + a
  a + b

so it seems like it should be possible to write a function that magically returns a function that requires the right number of arguments. So I could have a function:

f = (a,b,c,d,e,f) ->
  ..

if invoked with:

f(1,2)

it should return:

(c,d,e,f) ->

anyone know how to do that?

@puffnfresh
Copy link

Here's a functional solution:

function curry(f) {
    return function(x) {
        var g = f.bind(null, x);
        if(g.length == 0) return g();
        if(arguments.length > 1) return curry(g).apply(null, [].slice.call(arguments, 1));
        return curry(g);
    };
}

var sum = curry(function(x, y) {
    return x + y;
});

var incr = sum(1);
console.log(incr(2));

console.log(sum(1)(2));
console.log(sum(1, 2));

var tuple4 = curry(function(a, b, c, d) {
    return [a, b, c, d];
});

console.log(tuple4(1)(2, 3, 4));
console.log(tuple4(1, 2)(3, 4));
console.log(tuple4(1, 2)(3)(4));
console.log(tuple4(1, 2, 3)(4));

@liammclennan
Copy link
Author

Thanks for both of your great solutions. bind is great for currying - I didn't know that it could do that.

@jfromaniello
Copy link

I use bind all the time but take car with two things...

  • it changes the context, first argument is the new context.
  • some browsers doesnt support it yet.

The second one is easy to fix, you have to add a chunk of code from the mdn:

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment