手写柯里化(curry)支持占位符
请手写实现一个支持占位符(_)的柯里化函数,满足:curry(fn, placeholder), add(1)(2)(3) = 6。
回答
编译有声
function curry(fn, arity = fn.length, placeholder = curry.placeholder) {
return function curried(...args) {
const realArgs = args.slice(0, arity);
const hasPlaceholder = realArgs.some(a => a === placeholder);
const filled = realArgs.filter(a => a !== placeholder);
if (!hasPlaceholder && realArgs.length >= arity) {
return fn.apply(this, realArgs);
}
return function(...nextArgs) {
const merged = [];
let i = 0, j = 0;
for (const arg of realArgs) {
if (arg === placeholder && j < nextArgs.length) {
merged.push(nextArgs[j++]);
} else {
merged.push(arg);
}
}
merged.push(...nextArgs.slice(j));
return curried(...merged);
};
};
}
curry.placeholder = Symbol('placeholder');
const _ = curry.placeholder;
const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3));
console.log(curriedAdd(_, 2)(1)(3));
原理:收集参数直到函数元数(arity)满足,通过闭包保持已收集参数。