Skip to content

Instantly share code, notes, and snippets.

@unscriptable
Last active August 29, 2015 14:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save unscriptable/bb9f62add400fa45af61 to your computer and use it in GitHub Desktop.
Save unscriptable/bb9f62add400fa45af61 to your computer and use it in GitHub Desktop.
One way to create a curry function. Currying: http://en.wikipedia.org/wiki/Currying
module.exports = curry;
function curry (f) {
var arity = f.length;
var params = [];
var end = createEnd(f, arity);
return createCurried(params, arity, end);
}
function createEnd (f, arity) {
var src = 'return f(';
for (var i = 0; i < arity; i++) {
src += (i ? ', p[' : 'p[') + i + ']';
}
src += ');';
var endCall = new Function ('f', 'p', src);
return function end (p) {
return endCall(f, p);
};
}
function createCurried (collected, arity, end) {
return function () {
var params = concat(collected, arguments);
return params.length < arity
? createCurried(params, arity, end)
: end(params);
}
}
function concat (a, b) {
var al = a.length;
var bl = b.length;
var c = new Array(al + bl);
var i;
for (i = 0; i < al; ++i) c[i] = a[i];
for (i = 0; i < bl; ++i) c[i+al] = b[i];
return c;
}
@unscriptable
Copy link
Author

Seems like it'd be pretty fast because it avoids fn.apply(). However, since this this curry() ignores extra arguments, it can't be applied to functions with optional params that aren't reflected in the function's arity (length). :(

We would have to allow devs to supply an optional arity param to curry():

// splice has arity === 2, but has additional optional params
var spliceWithOneInsert = curry(array.splice.bind(array), 3);

@briancavalier
Copy link

Really cool. Here's a small variant that uses a dynamic compilation trick in order to give a name to the end function--might help during debugging.

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