Functional Programming
Function Composition & Piping
Master function composition and piping in JavaScript. Learn how to combine single-argument functions, write compose and pipe utility helpers, and build clean data processing pipelines.
1. Introduction
Function Composition and Piping are design patterns used to combine multiple functions to create a new function. Composition executes functions from right to left (like mathematical function composition: f(g(x))). Piping executes functions from left to right, matching the direction we read code.
2. Why It Matters
Processing data often requires passing it through a series of transformations (for example, trimming a string, converting it to lowercase, and replacing characters). Writing nested function calls like replace(lowercase(trim(str))) is difficult to read. Composition and piping flatten these structures into clean data processing pipelines.
3. Real-World Analogy
Think of an Industrial Water Purification Plant:
- Nested Functions (Manual buckets): You scoop raw water into a bucket, run it through filter A, pour the result into filter B, and then pour the result into filter C. You manually manage the intermediate steps.
- Piping (Connected pipes): You hook up water pipes in a line: Raw Water -> Filter A -> Filter B -> Filter C -> Clean Water. The water flows through the pipes automatically, without needing intermediate buckets.
4. Compose vs Pipe
Let's contrast the implementation and execution order of the two patterns:
1. Compose (Right-to-Left):
Executes functions from right to left, matching mathematical function notation.
2. Pipe (Left-to-Right):
Executes functions from left to right, matching the direction code is read.
5. Practical Example
This script demonstrates building a data pipeline to format and validate a user sign-up username:
6. Common Mistakes
- Trying to compose functions that accept multiple arguments: Composition and piping require functions to accept exactly one argument (unary functions). If a function requires multiple arguments, use currying or partial application to pre-bind parameters first.
7. Quick Quiz
Q1: What is the execution order of functions when using a pipe utility helper?
A) Right-to-Left
B) Left-to-Right
Answer: B — Piping executes functions from left to right, matching the direction code is read.
8. Scenario-Based Challenge
The Multi-Step API JSON Parser:
You want to write a pipeline that processes an API response string: "{ \"price\": \"19.99\" }". The pipeline must parse the JSON string, extract the price, convert the price to a number, and calculate the final cost with a 10% tax. Write this pipeline using pipe.
9. Debugging Exercise
Explain why this pipeline execution crashes, and how to fix it:
const pipe = (...fns) => (x) => fns.reduce((acc, fn) => fn(acc), x);const getLength = (str) => str.length; const addTen = (num) => num + 10; const capitalize = (str) => str.toUpperCase();
// Objective: calculate length, add 10, then capitalize output // Bug: wrong function ordering! const process = pipe(getLength, addTen, capitalize); process('hello'); // crashes with TypeError: str.toUpperCase is not a function! Why?
View Solution
Diagnosis: The pipeline passes the output of addTen (which is a number) to capitalize. Since numbers do not have a toUpperCase() method, the code crashes with a TypeError.
Fix: Capitalize the string first before calculating its length, or convert the final number to a string before capitalizing it:
const process = pipe(capitalize, getLength, addTen); // Correct order
console.log(process('hello')); // 15 (HELLO -> length 5 -> +10)
11. Interview Questions
🟢 Q1: Compare function composition and piping and list their differences.
Answer:
• Composition: Executes functions from right to left. It matches mathematical notation: compose(f, g)(x) is equivalent to f(g(x)).
• Piping: Executes functions from left to right. It matches the direction we read code: pipe(f, g)(x) is equivalent to g(f(x)).
Both patterns are used to combine multiple functions to create a new function, but piping is often preferred in software engineering because it reads in execution order.
12. Production Considerations
- • TypeScript Types: Typing function composition and piping in TypeScript can be complex. In production TypeScript environments, use utility libraries (like lodash/fp or fp-ts) that provide pre-typed
flow(pipe) andcomposehelpers.