F of G- Function Composition Explained
What Function Composition Actually Is
Function composition is simple: you take two functions and chain them together so the output of one becomes the input of the other. That's it. No fancy definitions, no complex theory.
The notation trips people up. When you see (f ∘ g)(x), it means "apply g first, then apply f to the result." Read it right to left.
You can also write it as f(g(x)). Same thing. Different notation.
Why This Matters
Composition builds complex behavior from simple pieces. Instead of writing one massive function that does everything, you write small functions and combine them.
This makes code easier to test. Easier to debug. Easier to reuse.
Most programmers ignore this principle and end up with tangled messes of code. You don't have to be one of them.
The Notation Table
| Notation | Meaning | Order of Operations |
|---|---|---|
| f(g(x)) | Apply g, then f | Inside out |
| (f ∘ g)(x) | Same as above | f after g |
| (g ∘ f)(x) | Apply f, then g | Reversed order |
Notice that f ∘ g is NOT the same as g ∘ f. Order matters. This trips up beginners constantly.
Math Examples
Let f(x) = 2x and g(x) = x + 3.
f(g(x)) = f(x + 3) = 2(x + 3) = 2x + 6
g(f(x)) = g(2x) = 2x + 3
Different results. Same functions, different order. That's composition.
Programming Examples
In JavaScript:
const compose = (f, g) => (x) => f(g(x)); const add2 = x => x + 2; const multiply3 = x => x * 3; const result = compose(multiply3, add2)(5); // add2(5) = 7, then multiply3(7) = 21
In Python:
from functools import reduce
def compose(*functions):
return reduce(lambda f, g: lambda x: f(g(x)), functions)
add2 = lambda x: x + 2
multiply3 = lambda x: x * 3
result = compose(multiply3, add2)(5)
# Output: 21
Real-World Analogy
Think of a factory assembly line. Raw material enters one machine, comes out transformed, enters the next machine, comes out more transformed.
Each machine is a function. The assembly line is composition.
Nobody builds a single machine that does everything. That's not how good systems work.
Common Mistakes
- Confusing the order of operations when reading notation
- Assuming composition is commutative (it's not)
- Not checking that output types match input types
- Over-complicating simple transformations
Getting Started: How To Compose Functions
Step 1: Identify your transformations. What needs to happen to the data? Break it into atomic steps.
Step 2: Write each step as a separate function. Keep them small. One job each.
Step 3: Combine them using composition. Start from the innermost operation and work outward.
Step 4: Test the composition. Verify each individual function works before blaming composition.
Step 5: Refactor when it gets hard to read. Too many composed functions is just as bad as one giant function.
When to Use Composition
- Data pipelines that transform input through multiple stages
- Building reusable transformation chains
- Simplifying complex conditional logic
- Creating middleware chains in web frameworks
The Bottom Line
Function composition isn't optional knowledge. It's a fundamental tool that separates readable, maintainable code from spaghetti.
You either learn to compose functions or you write code that nobody wants to maintain—including yourself, six months from now.
Pick one language. Practice with two simple functions. Chain them. See what happens. That's how you learn this.