Last active
January 28, 2019 20:36
-
-
Save ericcornelissen/2e79034936fa6517712baa0773ecbdba to your computer and use it in GitHub Desktop.
Simple and small wrapper to allow for partial function invocation
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
/** | |
* Make a function partially invokable, meaning that its | |
* arguments can be provided in any order. | |
* | |
* @example | |
* let addThreeNumbers = partial((a, b, c) => a + b + c); | |
* let plus4 = addThreeNumbers(1, _, 3); | |
* plus4(4); // => 8 | |
* | |
* @param {Function} fn The function to apply partial invokability to. | |
* @return {Function} A partially invokable function. | |
* @license The-Unlicense | |
*/ | |
function partial(fn) { | |
// Check if the provided argument is a function | |
if (typeof fn !== 'function') throw Error('Partial should be provided with a function'); | |
// Construct the initial memory | |
const arity = fn.length; | |
const allPlaceholders = [...Array(arity)].map(() => _); | |
// Return the function returned by the resolver. Where the | |
// resolver manages the memory of a partially invoked function | |
return (function resolver() { | |
// Create *local* memory to allow for reuse of a partially invoked function | |
const memory = Array.from(arguments); | |
return function() { | |
let args = memory.slice(0); | |
// Replace placeholder values with actual arguments from left to right | |
let j = 0; | |
for (let [i, arg] of args.entries()) { | |
if (arg === _) args[i] = arguments[j++]; | |
} | |
// Call fn if there is no more placeholder values, otherwise return | |
// another partially invoked function | |
const next = args.includes(_) ? resolver : fn; | |
return next.apply(null, args); | |
}; | |
}.apply(null, allPlaceholders)); | |
} | |
/* Variable to denote an argument placeholder, inspired by Scala */ | |
const _ = new class PartialPlaceholder { } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment