Lesson 1 of 11
Change the result, not the input
If a list cannot change, how can a program add an item to it?
In the previous lesson, we saw that pure functions do not cause side effects or change their inputs. A functional data structure follows that rule for its data: its operations use pure functions. Its values are immutable, meaning no operation can edit them in place. To add an item, an operation returns a new list.
Scala's enum lists a type's possible forms. For one concrete example, use an integer-only list with two forms: Nil means empty, and Cons(head, tail) is one cell holding a first value (head) and another list (tail). This lets a new cell point to an existing list.
enum IntList:
case Nil
case Cons(head: Int, tail: IntList)
val old = IntList.Cons(2, IntList.Nil)
val next = IntList.Cons(1, old)old still holds the list containing 2. next is one new cell for 1 followed by the exact list in old; the existing cell is not copied or changed. If a shared cell could be edited, both lists would reflect that edit. Because IntList cells are immutable, both versions remain valid. A functional update can reuse an unchanged tail without copying every element.