1a. Pipe Function from Left to Right using Reduce

const getName = (Obj) => Obj.name;
const makeUpperCase = (name) => name.toUpperCase();
const getFirstFourChar = (name) => name.substring(0, 4);
const reverseName = (name) => name.split("").reverse().join("");

const Pipe = (...Functions) => {
  return (...args) => {
    return Functions.reduce((output, Fn) => Fn(output), ...args);
  };
};

const output = Pipe(
  getName,
  makeUpperCase,
  getFirstFourChar,
  reverseName
)({ name: "Arjunan" });

console.log(output); // UJRA

1b. Pipe Function from Left to Right using For Loop

const Pipe = (...Functions) => {
  return (val) => {
    for (let fn of Functions) {
      val = fn(val);
    }
    return val;
  };
};

2a. Compose Function from Right to Left using Reduce

const getName = (Obj) => Obj.name;
const makeUpperCase = (name) => name.toUpperCase();
const getFirstFourChar = (name) => name.substring(0, 4);
const reverseName = (name) => name.split("").reverse().join("");

const Pipe = (...Functions) => {
  return (...args) => {
    return Functions.reduceRight((output, Fn) => Fn(output), ...args);
  };
};

const output = Pipe(
  reverseName,
  getFirstFourChar,
  makeUpperCase,
  getName
)({ name: "Arjunan" });

console.log(output); // UJRA

2b. Compose Function from Right to Left using For Loop

const Pipe = (...Functions) => {
  return (val) => {
    for (let i = Functions.length - 1; i >= 0; i--) {
      val = Functions[i](val);
    }
    return val;
  };
};

3. Return calculated Function values

Given an object which can have a function as a value at a nested level, create a function that will accept arguments as input and pass it through all the functions in the input object and return the computed value.

function Fn(obj) {
  return (...args) => {
    for (let key in obj) {
      const value = obj[key];
      if (typeof value === "function") {
        obj[key] = value(...args);
      }
      // Not null / undefined / string / number / boolean / array
      if (value && !Array.isArray(value) && typeof value === "object") {
        obj[key] = Fn(value)(...args);
      }
    }
    return obj;
  };
}

const obj = {
  a: {
    b: (a, b, c) => a + b + c,
    c: (a, b, c) => a + b - c,
  },
  d: (a, b, c) => a - b - c,
  e: null,
  f: 2,
  g: ["z", "y", "x"],
};

const ans = Fn(obj)(1, 1, 1);
console.log(ans);
// { a: { b: 3, c: 1 }, d: -1, e: null, f: 2, g: ["z", "y", "x"] };