Function Composition
Function composition means combining two or more functions into a new function.
How Function Composition Works
The new function applies the other functions one after another. The output of one function becomes the input to the next:
function double(x) {
return x * 2;
}
function increment(x) {
return x + 1;
}
// Compose function to apply increment then double
function composeTwo(f, g) {
return function (x) {
return f(g(x));
};
}
const incrementAndDouble = composeTwo(double, increment);
console.log(incrementAndDouble(3)); // 8
In this example, incrementAndDouble first increments the input by 1, then doubles it. The composeTwo function takes two functions f and g, and creates a new function where g is applied before f.
Practical Example
Suppose we need to process some text:
function lowerCase(input) {
return input.toLowerCase();
}
function trim(input) {
return input.trim();
}
function wrapInDiv(input) {
return `<div>${input}</div>`;
}
We can compose these functions to create a text processing pipeline:
const prepareText = composeTwo(composeTwo(wrapInDiv, lowerCase), trim);
console.log(prepareText(" Hello World ")); // <div>hello world</div>
The input string is first trimmed, then converted to lowercase, and then wrapped in a <div> tag.
Composing Multiple Functions
To compose more than two functions, we can write a general compose utility:
function compose(...funcs) {
return funcs.reduce(
(a, b) =>
(...args) =>
a(b(...args)),
);
}
const processText = compose(wrapInDiv, lowerCase, trim);
console.log(processText(" Functional Programming "));
// <div>functional programming</div>
This version uses reduce to chain the functions we pass in, so we can compose any number of them.
Benefits of Function Composition
- Readability: The composition shows which operations run and in what order
- Reusability: Each function can stay small and do one thing, and we can reuse it in other compositions
- Testing: We can test each function in the composition on its own
Further Learning
Libraries like Lodash and Ramda offer built-in utilities for function composition. These can be helpful when working with complex data transformation pipelines.