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!

Similar Posts