Learn How to Implement the compose() and pipe() Polyfill

Muhaymin Bin Mehmood

Muhaymin Bin Mehmood

· 3 min read
Learn How to Implement the compose() and pipe() Polyfill Banner Image
Learn How to Implement the compose() and pipe() Polyfill Banner Image

Functional programming often shines in JavaScript when you need to handle complex data flows with cleaner and more readable code. Two essential tools in this paradigm are the compose() and pipe() functions, commonly used to combine multiple functions into a single, seamless operation.

If you’ve ever used libraries like Redux, RxJS, or Lodash, you’ve likely encountered these utilities. But have you wondered how to create your own polyfills for compose() and pipe()? Let’s dive in!

Table of Contents

  1. What are compose() and pipe()?
  2. Why Create Polyfills?
  3. Implementing compose() Polyfill
  4. Implementing pipe() Polyfill
  5. Key Differences Between compose() and pipe()
  6. Real-World Examples
  7. Conclusion

1. What Are compose() and pipe()?

Compose

compose() is a higher-order function that takes multiple functions as arguments and returns a new function. This new function processes data by applying the given functions from right to left.

Syntax:

const composedFunction = compose(func1, func2, func3);
composedFunction(input); // Equivalent to func1(func2(func3(input)))

Pipe

pipe() is similar to compose(), but it processes the functions from left to right.

Syntax:

const pipedFunction = pipe(func1, func2, func3);
pipedFunction(input); // Equivalent to func3(func2(func1(input)))

2. Why Create Polyfills?

While libraries like Lodash and Ramda provide built-in implementations of these utilities, there are compelling reasons to build your own polyfills:

  • Learning: Gain a deeper understanding of JavaScript and functional programming.
  • Customization: Tailor the functions to your specific use case.
  • Minimize Dependencies: Reduce reliance on external libraries.

3. Implementing compose() Polyfill

To build a compose() polyfill, we chain functions in reverse order, where the result of one function serves as the input for the next.

Implementation:

function compose(...funcs) {
  return function (initialValue) {
    return funcs.reduceRight((accumulator, func) => func(accumulator), initialValue);
  };
}

Explanation:

  • ...funcs: Collects all arguments into an array of functions.
  • reduceRight(): Processes functions in reverse order, starting from the rightmost and moving to the left.
  • func(accumulator): Applies each function to the accumulated value.

Usage Example:

const add = (x) => x + 1;
const multiply = (x) => x * 2;

const composed = compose(add, multiply);
console.log(composed(5)); // Output: 11 (add(multiply(5)))

4. Implementing pipe() Polyfill

For pipe(), the logic is almost identical to compose(), but we process functions in the opposite order.

Implementation:

function pipe(...funcs) {
  return function (initialValue) {
    return funcs.reduce((accumulator, func) => func(accumulator), initialValue);
  };
}

Explanation:

  • reduce(): Processes functions from left to right.

Usage Example:

const add = (x) => x + 1;
const multiply = (x) => x * 2;

const piped = pipe(add, multiply);
console.log(piped(5)); // Output: 12 (multiply(add(5)))

5. Key Differences Between compose() and pipe()

Featurecompose()pipe()
OrderRight to LeftLeft to Right
Syntaxcompose(func1, func2)(input)pipe(func1, func2)(input)
Use CaseInspired by mathematical notation.More intuitive for data pipelines.

6. Real-World Examples

Example 1: Data Transformation

Suppose you need to transform user data by capitalizing names and appending a greeting.

const capitalize = (name) => name.toUpperCase();
const greet = (name) => `Hello, ${name}!`;

const composedGreeting = compose(greet, capitalize);
console.log(composedGreeting("john")); // Output: "Hello, JOHN!"

Example 2: Chaining API Data

For API responses, you might need to extract data, transform it, and calculate totals.

const parseResponse = (response) => response.data;
const calculateTotal = (data) => data.reduce((sum, item) => sum + item.price, 0);

const processApiData = pipe(parseResponse, calculateTotal);
const response = { data: [{ price: 10 }, { price: 20 }, { price: 30 }] };
console.log(processApiData(response)); // Output: 60

7. Conclusion

Creating polyfills for compose() and pipe() is a rewarding exercise that deepens your understanding of functional programming principles. These tools are invaluable for building clean, readable, and maintainable code, especially when dealing with complex data flows.

Whether you’re building your next project or improving your JavaScript skills, mastering compose() and pipe() will elevate your development game.

What’s Next?
Try implementing these polyfills on your own and experiment with real-world use cases. Happy coding! 🎉

Muhaymin Bin Mehmood

About Muhaymin Bin Mehmood

Front-end Developer skilled in the MERN stack, experienced in web and mobile development. Proficient in React.js, Node.js, and Express.js, with a focus on client interactions, sales support, and high-performance applications.

Copyright © 2024 Mbloging. All rights reserved.