Skip to content

Instantly share code, notes, and snippets.

@sunjay
Last active December 9, 2015 03:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sunjay/adcbaa52666480f54aab to your computer and use it in GitHub Desktop.
Save sunjay/adcbaa52666480f54aab to your computer and use it in GitHub Desktop.
An example of currying in JavaScript using the .length property of function to dictate when to evaluate
/**
* Returns a curry-able version of a function
* The parameters for this function are exactly the same as .bind()
* context is optional - if null, the default context will be used
* Any arguments passed in after context will automatically be passed
* in before any other arguments that are applied
*/
Function.prototype.curry = function(context) {
var f = this;
var baseArgs = Array.prototype.slice.call(arguments);
// It's important to initially return a function and not just curryApply
// so that the closure for args gets created uniquely on each initial call
// of the curried function f
return function() {
var args = baseArgs.slice();
var curryApply = function() {
args = args.concat(Array.prototype.slice.call(arguments));
if (args.length >= f.length) {
return f.apply(context || this, args);
}
return curryApply;
};
return curryApply.apply(context || this, arguments);
};
}
var a = function(q, r, x) {
return q + r + x;
}.curry();
// all of these are equivalent
console.log(a(1, 2, 3));
console.log(a(1)(2)(3));
console.log(a(1)(2, 3));
console.log(a(1, 2)(3, 4));
// After curry() is applied, b is a function that takes 2 arguments, not 3
var b = function(q, r, x) {
return q + r + x;
}.curry(1);
// all of these are equivalent
console.log(b(2, 3));
console.log(b(2)(3));
// since this is JavaScript, extra arguments don't matter
console.log(b(2)(3, 4));
// a fortunate/unfortunate consequence of this (depending on your perspective)
// is that the following is also valid
// a "fix" for this is to count the number of calls as well as the arguments
// applied and then compare the maximum of those numbers to f.length
console.log(b(2)()()()()(3));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment