Coding Challenge Practice – Question 22
The task is to create a curry function that also supports a placeholder. The goal is to transform a function that takes multiple arguments into a sequence of functions, each taking one or more arguments. If fewer arguments than the function needs are provided, a new function waiting for the rest is returned. The boilerplate code:
function curry(fn) {
}
curry.placeholder = Symbol()
First, a variable for the placeholders is created
const placeholder = curry.placeholder
A curried function that accepts the arguments is called first. The function checks if there are enough non-placeholder arguments.
const actualArgs = args.slice(0, fn.length);
const hasPlaceholder = actualArgs.includes(placeholder);
const nonPlaceholderCount = actualArgs.filter(arg => arg !== placeholder).length;
If there are enough real arguments, the function is called
if (nonPlaceholderCount >= fn.length && !hasPlaceholder) {
return fn(...actualArgs);
}
Otherwise, a function that receives the next set of arguments is called. When the next function is called, a process called argument merging occurs. Placeholders are replaced with arguments from the new function until the number of arguments required to call the original functions is complete.
return function next(...nextArgs) {
let merged = [];
let argsIndex = 0;
let nextIndex = 0;
while (argsIndex < args.length || nextIndex < nextArgs.length) {
if (argsIndex < args.length) {
if (args[argsIndex] === placeholder && nextIndex < nextArgs.length) {
merged.push(nextArgs[nextIndex++]);
argsIndex++;
} else {
merged.push(args[argsIndex++]);
}
} else {
merged.push(nextArgs[nextIndex++]);
}
}
return curried(...merged);
}
The function goes through the list of arguments, one after the other. If there is a normal value, it keeps its place. If there is a placeholder, it takes the next available value from the next function and replaces the placeholder in that position.
Here’s the final code:
function curry(fn) {
// your code here
const placeholder = curry.placeholder;
function curried(...args) {
const actualAgs = args.slice(0, fn.length);
const hasPlaceholder = actualAgs.includes(placeholder);
const nonplaceholderCount = actualAgs.filter(arg => arg !== placeholder).length
if(nonplaceholderCount >= fn.length && !hasPlaceholder) {
return fn(...actualAgs);
}
return function next(...nextArgs) {
let merged = [];
let argsIndex = 0;
let nextIndex = 0;
while(argsIndex < args.length || nextIndex < nextArgs.length) {
if(argsIndex < args.length) {
if(args[argsIndex] === placeholder && nextIndex < nextArgs.length) {
merged.push(nextArgs[nextIndex++]);
argsIndex++;
} else {
merged.push(args[argsIndex++])
}
} else {
merged.push(nextArgs[nextIndex++])
}
}
return curried(...merged)
}
}
return curried;
}
curry.placeholder = Symbol()
That’s all folks!