We’ve now gone through much of the nuts and bolts of Clojure’s collections and surveyed many of their abstractions. What we haven’t yet emphasized and explored are two characteristics that are shared by all of Clojure’s data structures: they are immutable, and they are persistent.
We explored the notion of immutability in Chapter 2 and learned how the value semantics provided by working with immutable entities can be a great simplifying force. However, you might have some lingering concerns. For example, consider this operation over numbers:
(+ 1 2) ;= 3
3
here is a value entirely
separate from the arguments to +
.
Certainly, the act of adding numbers doesn’t modify one of the addends to
make it be another number. This is in stark contrast
to how most data structures work in languages that encourage unfettered
mutation, like Python here:
>>> lst = [] >>> lst.append(0) >>> lst [0]
append
really did modify lst
. That has many implications, not necessary
all pleasant, but you can be certain that such operations are
efficient, almost regardless of the size of the
collection in question. On the other hand, this looks like it might be
problematic:
(def v (vec (range 1e6)));= #'user/v (count v) ;= 1000000 (def v2 (conj v 1e6))
;= #'user/v2 (count v2) ;= 1000001 (count ...
No credit card required