Last active
December 9, 2015 03:06
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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