The Heart of FP โ€” Pure Functions

Lesson 2: The Heart of FP โ€” Pure Functions

Everything in functional programming flows from one idea: the pure function. A pure function has exactly two properties:

  1. Deterministic โ€” the same inputs always produce the same output.
  2. Side-effect free โ€” it never touches anything outside its inputs and return value.
// IMPURE โ€” mutates external state and prints
let total = 0;
function addToTotal(x) {
  total += x;                // mutates a variable outside itself
  console.log("added " + x); // I/O side effect
  return total;
}

// PURE โ€” nothing but input โ†’ output
function add(a, b) {
  return a + b;              // that's it
}

Side Effects: The Hit List

Anything a function does besides returning a value from its inputs counts as a side effect:

  • Mutating a variable, array, or object outside the function
  • Writing to disk, the network, or a database
  • Printing to the console
  • Reading the current time or a random number
  • Changing the DOM or global configuration

Each of these makes behavior depend on when and where the function runs โ€” which is exactly what makes bugs hard to reproduce.

Referential Transparency

An expression is referentially transparent when you can replace it with its value without changing the program's behavior. Pure functions give you this property, which means you can reason about code like algebra: if double(21) always equals 42, you can substitute freely. This is what makes refactoring safe and debugging surgical.

Not a ban: Functional programs do print, talk to databases, and call the network. The trick is isolating side effects at the edges of the program while keeping the core pure โ€” a pattern called "functional core, imperative shell" that we'll visit in Lesson 8. Purity is about containment, not abstinence.
PURE input pure function output same input โ†’ same output ยท nothing else touched IMPURE input impure function output? mutates globals prints ยท I/O

Why Purity Wins

ConcernWhat purity gives you
TestingNo mocks, no setup, no cleanup. Call it, assert on the return value, done.
PredictabilityA function can't secretly change the state of your app or library.
CachingSame input โ‡’ same output, so results can be memoized safely.
ParallelismPure functions share nothing, so they can run on multiple cores without locks.
ComposabilityFunctions that don't meddle combine reliably โ€” the topic of Lesson 4.

๐Ÿง  Knowledge Check

1. Which of the following is a pure function?

2. "Referential transparency" means:

3. Functional programs still do I/O and talk to databases. How is that reconciled with purity?

Further Reading