Skip to content

Latest commit

 

History

History
90 lines (68 loc) · 3.7 KB

File metadata and controls

90 lines (68 loc) · 3.7 KB

Solution

Submission link - https://bigfrontend.dev/problem/implement-curry-with-placeholder/discuss/769

/**
 * @param { Function } func
 */
function curry(func) {

  return function curried(...args) {   // we need to return a function to make it curry-able.

    const sanitizedArgs = args.slice(0, func.length);
    const hasPlaceholder = sanitizedArgs.some(arg => arg == curry.placeholder);

    if(!hasPlaceholder && sanitizedArgs.length == func.length) {
      return func.apply(this, sanitizedArgs);
    }

    return function next(...nextArgs) {
      return curried.apply(this, mergeArgs(sanitizedArgs, nextArgs));
    }

  } 
}

function mergeArgs(args, nextArgs) {
  let result = [];
  
  args.forEach((arg, idx) => {
    if(arg == curry.placeholder) {
      result.push(nextArgs.shift());
    } else {
      result.push(arg);
    }
  });

  return [...result, ...nextArgs];
}

curry.placeholder = Symbol()

Short story

This is an extended version of problem 1. Implement curry() where we need to replace placeholder value with the next argument values. After 1.5 days of struggle and peeking at few a solutions, here I am presenting you with an explanation.

Algorithm

Part 1 -

  1. We create a function called curried that we return to take arguments
  2. We sanitize arguments to remove extra arguments (possible due to placeholders)
  3. We check if sanitized arguments sanitizedArgs >= function func parameters or not
  4. We also check if any placeholder is present in the given arguments
  5. If the above both the conditions are true then we call func with all arguments we received (normal currying case)

Part 2 -

  1. Else we will merge args and nextArgs to replace placeholders with actual available arguments
  2. We will iterate over args and push the first element of nextArgs (also remove it from nextArgs) if we find a placeholder element in args
  3. Once the loop is over, we will merge the replaced arguments with the remaining nextArgs

Code overview

Part 1 -

  1. To make a function curry-able, we return a function curried
  2. The curried will take arguments args
  3. We will sanitize (remove placeholders) args to count the length of the arguments
  4. We will also check if these arguments have the placeholder
  5. We will check if sanitizedArgs.length (sanitize arguments) == func.length (total parameters) and there is no placeholder in the arguments
    1. If both the above conditions are true then we directly call func with sanitizedArgs arguments
    2. Else we will return another function next (because few arguments are still pending) to collect the next arguments
  6. The next function will call the curried function which will -
    1. Take sanitizedArgs arguments and nextArgs and merge them to replace placeholders with next arguments
  7. We will call the curried function with merged arguments

Part 2 - mergeArgs

  1. We will create a result array to add valid and replaced arguments
  2. We will iterate over args and keep adding the first element from nextArgs if the current argument arg from args contains the placeholder
  3. When we add the first element from nextArgs then we remove that element from it too. nextArgs.shift()
  4. If there is no placeholder then we will push arg in the result array
  5. Once the loop is completed, we will merge the result and the remaining nextArgs.
    1. This is a case where nextArgs > args
  6. We will return merged arguments result

That's it.


I'm excited to improve the solution and code walkthrough. Feel free to drop a comment, or send a PR or send memes @knowkalpesh.