Skip to content

Instantly share code, notes, and snippets.

@Bclayson
Last active February 23, 2016 06:26
Show Gist options
  • Save Bclayson/6e2610671c432d7f1bdb to your computer and use it in GitHub Desktop.
Save Bclayson/6e2610671c432d7f1bdb to your computer and use it in GitHub Desktop.
// A function decorator that returns a curryable version of the original function with an arbitrary number of arguments
// This is an introspective helper function that allows us get the parameter names of our original function and return it as an array
function getParamNames(func) {
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /([^\s,]+)/g;
var fnStr = func.toString().replace(STRIP_COMMENTS, '');
var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
if (result === null)
result = [];
return result;
}
// another small helper in created the closing brackets for the string we pass to the function constructor
function repeater(thing, times) {
var result = '';
for (var i = 0; i < times; i++) {
result += thing
}
return result
}
// Main Function/Decorator: takes a function and returns a version that is curryable
function partialized(fn) {
var fnString = '';
var fnArgs = '';
var fnParameters = getParamNames(fn)
// for loop builds a string version of our final function that will be passed to the Function constructure
for (var i = 0; i < fnParameters.length; i++) {
fnString += 'return function (' + fnParameters[i] + ') {';
if (i < fnParameters.length - 1) {
fnArgs += fnParameters[i] + ', '
} else {
fnArgs += fnParameters[i]
}
}
// the final curry has to call the function with the arguments passed to it
var called = 'fn(' + fnArgs + ')'
// add all the closing brackets
fnString += 'return ' + called + repeater('}', fnParameters.length)
// the function constructor does not create a closure.
// So we have to explicitly pass in the original function
// in order for it's environment to be available inside of the newly created function
// if we don't do this, it will complain that 'fn' is undefined. this is kind of a JavaScript gotcha IMO.
return new Function('fn', fnString)(fn);
}
// original function that adds together five items
function addBunch(a, b, c, d, e) {
return a + b + c + d + e;
}
var partialAdd = partialized(addBunch);
// now we can partially apply each argument
var v = partialAdd(5);
var w = v(5);
var x = w(3);
var y = x(2);
var z = y(30);
console.log(z)
// or . . . .
var result = partialAdd(5)(4)(3)(2)(6);
console.log(result);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment