Create Currying Functions with Nested Objects

Currying is a powerful technique in functional programming that transforms a function with multiple arguments into a series of functions that each take a single argument. This concept becomes particularly interesting when applied to objects with nested functions, enabling more flexible and reusable code. In this interview article, we’ll walk through how to create a currying mechanism for such nested objects.

Given an object with nested functions as below

let testObj = {
  a: {
    b: (a, b, c) => a + b + c,
    c: (a, b, c) => a + b - c,
  },
  d: (a, b, c) => a - b - c,
  e: 1,
  f: true,
};

Our goal is to:

  1. Create a currying function that can handle these nested structures.
  2. Apply a set of arguments to all functions within the nested object.
console.log(pipe(testObj)(1, 1, 1));
// output should be as below
{
  a: {
    b: 3,
    c: 1
  },
  d: -1,
  e: 1,
  f: true
}

Step-by-Step Solution:

1. Creating the Pipe Function

We need a function pipe that takes an object and returns a function that can apply arguments to all functions within that object, including nested functions.

2. Recursively Apply Arguments

The pipe function should recursively traverse the object, apply arguments to functions, and return the modified object.

3. Combining Everything

Let’s break down the solution and then provide the complete code.

The Pipe Function

The pipe function will accept an object and return a function that applies the provided arguments to each function within the object.

const pipe = (obj) => {
  return (...args) => {
    for (let i in obj) {
      const val = obj[i];
      if (typeof obj[i] === "function") {
        obj[i] = val(...args);
      } else if (typeof obj[i] === "object" && obj[i] !== null) {
        obj[i] = pipe(obj[i])(...args);
      }
    }
    return obj;
  };
};

In this implementation:

  • We loop through each key in the object.
  • If the value is a function, we call it with the provided arguments.
  • If the value is an object, we recursively call pipe on the nested object.
  • Finally, we return the modified object.

4. Using the Pipe Function

Now we can use the pipe function to transform our testObj object.

console.log(pipe(testObj)(1, 1, 1));

This will apply the arguments (1, 1, 1) to all functions within the test object, including those nested within other objects, Running the above code will output as below.

{
  a: {
    b: 3,
    c: 1
  },
  d: -1,
  e: 1,
  f: true
}

In this interview article, we explored how to create a currying function that works with nested objects in JavaScript. The pipe function allows us to apply a set of arguments to all functions within an object, making our code more flexible and reusable. This technique can be particularly useful in functional programming scenarios and when dealing with complex nested structures.