Skip to content

Instantly share code, notes, and snippets.

@kschat
Last active August 29, 2015 14:21
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 kschat/cc820cf1de65796840e1 to your computer and use it in GitHub Desktop.
Save kschat/cc820cf1de65796840e1 to your computer and use it in GitHub Desktop.
My attempt at implementing currying in JS
!function() {
'use strict';
// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
var cloneArgs = function(props) {
var args = new Array(props.length);
for(var i = 0; i < props.length; i++) {
args[i] = props[i];
}
return args;
};
/*
* Currying in JS. Uses the following rules
* where f = function to curry, n = args passed, m = args function takes:
* 1. If n == 0 return f
* 2. If n < m return curried f with n args
* 3. If n == m call f with args. If the result is a function, curry result.
Finally, return result.
* 4. If n > m call f with the first n args. If the result is a function, curry
* it and apply remaining args to result. Finally, return function.
*
* Rules lifted from this great answer: http://stackoverflow.com/a/27996545/983194
*
* curry :: (* -> a) -> (* -> a)
*/
var curry = function curry(func) {
func = func || this;
return function f() {
if(arguments.length === 0) { return f; }
var args = cloneArgs(arguments);
if(args.length < func.length) {
return curry(func.bind.apply(func, [null].concat(args)));
}
var firstArgs = args.slice(0, func.length + 1);
var result = func.apply(null, firstArgs);
return typeof result === 'function'
? curry(result).apply(null, args.slice(func.length))
: result;
};
};
Function.prototype.autoCurry = Function.prototype.autoCurry || curry;
}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment