F1 · Algebra
Immutability & binding
A name is a label fixed to a value, not a box you write into. Values do not change; you build new ones. And in Elixir the equals sign does not assign — it matches.
This is the property the last two modules quietly relied on. Substitution is only valid because a name keeps its value, and composition is only safe because a function cannot reach back and alter its inputs. We separate three ideas that often blur together: binding a name, matching with the equals sign, and the immutability of the data itself.
Names, not boxes
In mathematics, writing x = 3 does not allocate a cell that might later hold something else. It names the value 3 for the rest of the discussion. A binding attaches a name to a value; it does not create a container.
Elixir lets you rebind a name — write x = 1 and later
x = 2 — but that is the name pointing at a new value, not the old value
changing. Anything that already captured the old value still sees it. Step through the classic case.
- bind
- attach a name to a value; x = 3 makes x mean 3.
- rebind
- point a name at a new value; the old value is untouched.
- immutable
- a value never changes after it is made.
- pin
^xmatches the current value of x instead of rebinding it.
Binding · rebinding moves the name, not the value
Algebra
A name denotes a value. Naming something else does not alter what the first name meant.
Elixir
x = [0 | x] rebinds x; a y that aliased the old list still holds it.
Rebinding is not mutation. The value a name held is safe from anything you do to the name afterwards.
Equals is a match
In Elixir = is the match operator, not assignment. It asks
whether the left side can be made to match the right, binding any names on the left as a side of that
match. A bare name always matches, which is why x = 1 looks like assignment —
but a pattern on the left does real work, and a value on the left is a check.
Take x already bound to 1, and try a few matches.
The pin ^ says “match against the current value” rather than rebind.
The match operator · given x = 1
Algebra
An equation states that two sides are equal; solving it determines the unknowns.
Elixir
= matches and binds; ^x pins; a failed match raises a MatchError.
Reading = as a match, not a store, is the shift that makes the rest of
Elixir read clearly — F1.08 turns it into solving by structure.
Data that holds still
Values themselves are immutable. You never change a map or a list in place; an operation that looks like an update returns a new value and leaves the original exactly as it was. Because the new value can share the parts it did not change — the structural sharing of F0.1.3 — this is cheap, not wasteful.
Apply an operation to a small map and watch the original. It does not move.
Immutable update · the original is never touched
Algebra
A value is what it is; producing another value does not revise the first.
Elixir
Map.put/3 returns a new map; the one you passed in is unchanged and safe to share.
Nothing changes underneath a reference you are holding. That is what makes immutable data safe to pass between functions — and, in F0.2, between processes.
What this lands
Three separate things sat behind one word. Binding names a value without a container; the match operator
reads = as a test, not a store; and immutability keeps every value fixed once made.
Together they are why F1.02 could substitute equals for equals and why F1.03 could compose functions
without surprise — nothing a later step does can rewrite an earlier value. The same property makes data
safe to share across the processes of F0.2, and the structural sharing of F4 makes it inexpensive. Next,
F1.05 puts immutable values into collections and maps a function across them.
Next: F1.05 — Sets, sequences & mappings (planned) — applying one function across a whole collection. The rest of F1 is listed on the chapter page.