Lesson 2 / 25
Pure Functions and Referential Transparency
Same input, same output, nothing else touched.
What makes a function pure
A pure function (1) always returns the same output for the same arguments and (2) has no observable side effects: it does not modify its arguments or global state, write to the console, read the clock, call the network or throw based on hidden state. Pure functions are referentially transparent: any call can be replaced by its result without changing the program's behaviour. That property lets you reason about code by substitution, cache results safely, run calls in parallel and test with plain inputs and expected outputs, no mocks required.
Pure and impure side by side
Spot the hidden inputs and outputs.
// Pure: result depends only on the arguments
const addTax = (price: number, rate: number): number => price * (1 + rate);
// Impure: reads hidden mutable state
let taxRate = 0.2;
const addTaxImpure = (price: number) => price * (1 + taxRate);
// Impure: mutates its argument
function addItem(cart: string[], item: string): string[] {
cart.push(item); // caller's array changes
return cart;
}
// Pure alternative: return a new array
const addItemPure = (cart: readonly string[], item: string): string[] => [...cart, item];
// Impure: depends on the clock
const isExpired = (expiry: Date) => expiry.getTime() < Date.now();
// Pure alternative: pass "now" in
const isExpiredAt = (expiry: Date, now: Date) => expiry.getTime() < now.getTime();Pass time and randomness in
Functions that call Date.now() or Math.random() are impure. Accept the current time or a random value as a parameter and the function becomes pure and trivially testable.
Quick check: Which function is pure?
- `(a, b) => a + b`
- `(x) => { console.log(x); return x; }`
- `() => Math.random()`
- `(arr) => { arr.sort(); return arr; }`
Answer
`(a, b) => a + b` — Logging, randomness and in-place sorting are all side effects or hidden inputs.