58 lines
1.9 KiB
JavaScript
58 lines
1.9 KiB
JavaScript
function curry(func, arity = func.length, guard) {
|
|
arity = guard ? func.length : arity;
|
|
arity = Number.parseInt(arity, 10);
|
|
if (Number.isNaN(arity) || arity < 1) {
|
|
arity = 0;
|
|
}
|
|
const wrapper = function (...partialArgs) {
|
|
const holders = partialArgs.filter(item => item === curry.placeholder);
|
|
const length = partialArgs.length - holders.length;
|
|
if (length < arity) {
|
|
return makeCurry(func, arity - length, partialArgs);
|
|
}
|
|
if (this instanceof wrapper) {
|
|
return new func(...partialArgs);
|
|
}
|
|
return func.apply(this, partialArgs);
|
|
};
|
|
wrapper.placeholder = curryPlaceholder;
|
|
return wrapper;
|
|
}
|
|
function makeCurry(func, arity, partialArgs) {
|
|
function wrapper(...providedArgs) {
|
|
const holders = providedArgs.filter(item => item === curry.placeholder);
|
|
const length = providedArgs.length - holders.length;
|
|
providedArgs = composeArgs(providedArgs, partialArgs);
|
|
if (length < arity) {
|
|
return makeCurry(func, arity - length, providedArgs);
|
|
}
|
|
if (this instanceof wrapper) {
|
|
return new func(...providedArgs);
|
|
}
|
|
return func.apply(this, providedArgs);
|
|
}
|
|
wrapper.placeholder = curryPlaceholder;
|
|
return wrapper;
|
|
}
|
|
function composeArgs(providedArgs, partialArgs) {
|
|
const args = [];
|
|
let startIndex = 0;
|
|
for (let i = 0; i < partialArgs.length; i++) {
|
|
const arg = partialArgs[i];
|
|
if (arg === curry.placeholder && startIndex < providedArgs.length) {
|
|
args.push(providedArgs[startIndex++]);
|
|
}
|
|
else {
|
|
args.push(arg);
|
|
}
|
|
}
|
|
for (let i = startIndex; i < providedArgs.length; i++) {
|
|
args.push(providedArgs[i]);
|
|
}
|
|
return args;
|
|
}
|
|
const curryPlaceholder = Symbol('curry.placeholder');
|
|
curry.placeholder = curryPlaceholder;
|
|
|
|
export { curry };
|