Latticework

Command Palette

Search for a command to run...

Functional Programming Fundamentals

Immutability

16 min

Explanation

An immutable value can't be changed after creation — Python's str, int, float, tuple, and frozenset are all immutable; list, dict, and set are mutable. Immutability is a big part of what makes pure functions possible: if a value literally CAN'T be changed, no function can accidentally mutate it out from under you.

t = (1, 2, 3)
t[0] = 99   # TypeError: 'tuple' object does not support item assignment

# instead, build a new tuple:
t = (99,) + t[1:]
Try it

Dicts can't be dict keys (they're mutable, so not hashable) -- freezing one into a sorted tuple of pairs is the standard way to make a dict-like value usable as a cache key.

Loading editor…
Explanation

The general pattern for "modifying" an immutable value is always the same: build a NEW value that looks like the old one with your one change applied, rather than mutating in place:

def update_immutable(t, index, value):
    return t[:index] + (value,) + t[index + 1:]

print(update_immutable((1, 2, 3), 1, 99))   # (1, 99, 3) -- a new tuple

This costs more memory than mutating in place would (you're allocating a new object every time) — that's the real tradeoff immutability makes: safety and predictability, in exchange for some extra allocation. For small, frequently-shared values (config, cache keys, function arguments you don't want callers accidentally mutating), that tradeoff is usually well worth it.

Exercise

Write `freeze_config(d)`: convert a dict `d` into an immutable, hashable representation — a tuple of its `(key, value)` pairs, sorted by key.

Exercise

Write `update_immutable(t, index, value)`: given a tuple `t`, return a NEW tuple with the element at `index` replaced by `value` — tuples can't be mutated in place, so build the replacement via slicing.

Quiz

Why can't you do `my_tuple[0] = 5` in Python?

Checkpoint

You can convert a mutable dict into an immutable, hashable tuple representation, and "modify" an immutable tuple by constructing a new one.