Last active
February 23, 2016 06:26
-
-
Save Bclayson/6e2610671c432d7f1bdb to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// 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