Curry Functions With Placeholders
Transform multi-argument functions into curried variants that support placeholders and partial application.
Code
export const curryPlaceholder = Symbol("curry.placeholder");
export function curry(fn, arity = fn.length) {
if (typeof fn !== "function") throw new TypeError("fn must be a function");
if (!Number.isInteger(arity) || arity < 0) throw new RangeError("arity must be a non-negative integer");
return function curried(...args) {
const supplied = args.slice(0, arity);
if (supplied.length === arity && !supplied.includes(curryPlaceholder)) {
return fn.apply(this, supplied);
}
return function next(...more) {
const merged = [];
let cursor = 0;
for (const argument of args) {
if (argument === curryPlaceholder && cursor < more.length) {
merged.push(more[cursor]);
cursor += 1;
} else {
merged.push(argument);
}
}
while (cursor < more.length) {
merged.push(more[cursor]);
cursor += 1;
}
return curried.apply(this, merged);
};
};
}
export function uncurry(curried) {
if (typeof curried !== "function") throw new TypeError("curried must be a function");
return (...args) => args.reduce((fn, argument) => fn(argument), curried);
}Report a problem with this exampleOpens a pre-filled issue on GitHub.