The Functional Mind
Imagine describing a photograph. You don't say "first the camera captured the tree, then it added the sky, then it modified the colors." You simply describe what is: "A tree stands against a blue sky."
This is functional thinking: describing what things are, not how to change them. It's the world of mathematics, of definitions, of relationships. It's a different way of seeing computation entirely.
Thinking in Transformations
The functional mind sees computation as transformation. Data flows in. Different data flows out. Nothing is modified---new things are created.
// Moving a chess piece, functionally
new_board = board with:
[e2] = empty
[e4] = board[e2]
// board is unchanged. new_board is a new value.This might seem wasteful---why create a new board instead of modifying the existing one? But this choice has profound consequences, as we'll see.
Values, Not Variables
In functional thinking, we don't have variables that change. We have values that we give names to.
score = 10 // "score" names the value 10
new_score = score + 5 // "new_score" names a different value
// score is still 10. Always will be.A name binds to a value permanently. If you need a different value, use a different name (or describe how the new value relates to the old).
Functions: Input to Output
A pure function is a pure relationship: given these inputs, produce this output. Always. Reliably.
opposite(white) = black
opposite(black) = white
square_color(a1) = black
square_color(a2) = white
// ... and so onPure functions have a magical property: calling them has no effects other than computing the result. They don't modify anything. They don't depend on hidden state. Given the same inputs, they always return the same output.
// Pure: only depends on input
is_valid_position(row, col) =
row >= 1 AND row <= 8 AND col >= 1 AND col <= 8
// Impure: depends on external state
is_my_turn() = current_player == my_color // what's "current"?Composition: Plugging Functions Together
If functions are transformations, we can chain them:
// Data flows through a pipeline
result = moves
|> filter(is_legal)
|> sort_by(quality)
|> take_first
// Read: "take moves, keep the legal ones, sort by quality, take the first"This is like an assembly line. Raw material enters. Each station transforms it. The final product emerges. No station modifies the original---each creates something new.
Recursion: Self-Reference Instead of Loops
Without mutable variables, how do we repeat things? We can't have a counter that increments. Instead, we use recursion: a function that refers to itself.
count_pawns(squares) =
if squares is empty:
0
else if first(squares) is a pawn:
1 + count_pawns(rest(squares))
else:
count_pawns(rest(squares))This is a definition, not a procedure. It says: "The count of pawns in a list is either zero (if empty) or the count of the rest plus one (if there's a pawn) or just the count of the rest (otherwise)."
Immutability: Nothing Changes
The functional mind embraces immutability: once a value exists, it never changes.
original_board = starting_position
after_move_1 = apply_move(original_board, "e2-e4")
after_move_2 = apply_move(after_move_1, "e7-e5")
// All three boards exist, all unchanged
// We have a history by constructionThis connects to our earlier discussion of Parmenides: new things come into being rather than old things changing. The functional mind lives in a Parmenidean universe.
The Functional Worldview
The functional mind sees the world as:
- Values: Immutable data that simply exists
- Functions: Pure mappings from inputs to outputs
- Composition: Building complex transformations from simple ones
- Expressions: Descriptions of what things are, not commands to execute
Languages like Haskell, Clojure, and Elm embrace this worldview deeply. Others like JavaScript and Python let you write in this style if you choose.
Why Choose Immutability?
The functional style might seem restrictive. Why give up the ability to modify things?
- Predictability: Pure functions always behave the same
- Testing: No hidden state means easy testing
- Parallelism: Nothing changes, so nothing conflicts
- Debugging: You can inspect any past state
The functional mind thinks: "I don't change the world; I describe how new things relate to existing things." It's a mathematical worldview, serene and predictable. But there's yet another way to think---one that sees the world as a community of entities, each with its own knowledge and behavior.