Skip to content

Instantly share code, notes, and snippets.

@ericcornelissen
Last active January 28, 2019 20:16
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 ericcornelissen/09e11b331a901c340a05664e85a02b69 to your computer and use it in GitHub Desktop.
Save ericcornelissen/09e11b331a901c340a05664e85a02b69 to your computer and use it in GitHub Desktop.
Simple and small wrapper to curry functions of any arity
/**
* Curry a function of any length. Note that a curried
* function accepts only one argument at the time.
*
* @example <caption>Simple usage</caption>
* let addTwoNumbers = curry((x, y) => x + y);
* addTwoNumbers(1); // => Function[y => 1 + y]
* addTwoNumbers(1)(3); // => 4
*
* @example <caption>Incorrect usage</caption>
* let addTwoNumbers = curry((x, y) => x + y);
* addTwoNumbers(1, 3); // => Function[y => 1 + y] | The second argument is ignored
* addTwoNumbers(1, 3)(3); // => 4
*
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
* @license The-Unlicense
*/
function curry(fn) {
// Check if the provided argument is a function
if (typeof fn !== 'function') throw Error('Curry should be provided with a function');
// Get the arity of the function to curry
const arity = fn.length;
// Return the return value of resolver() which is the curried function
return (function resolver() {
// Create *local* memory to allow for reuse of the curried function
const memory = Array.from(arguments);
// Return the curried function
return function(x) {
// Add the provided argument to the memory
let args = memory.slice(0);
args.push(x);
// Call fn if enough arguments have been provided, otherwise return
// another curried function
const next = args.length >= arity ? fn : resolver;
return next.apply(null, args);
};
}());
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment