Now that we’ve got primitives out of the way, we need to start doing something with them. Single atomic values are great and all, but things get much more interesting when we start globbing them all together. As you’ll see soon enough, data manipulation is one of Clojure’s strong suits.
What makes Clojure so good at manipulating collections? It comes down to three things: immutability, persistence, and the sequence abstraction. Every one of Clojure’s built-in collection types has these properties and is thus unified in its API’s appearance and behavior.
As the great Alan J. Perlis (an early computer science pioneer) put it:
It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures.
This chapter introduces Clojure collections and where/how to use them. Finally, we wrap things up by showing you how to build your own feature-complete types that look and behave just like the rest of Clojure’s collections by leveraging Clojure’s capacity for interface polymorphism.
Immutability means that a Clojure data structure, once created, can never change. You can only “modify” an immutable data structure by creating a new data structure that is a copy of the old, with the desired changes in place.
Immutability also means that Clojure data structures, however deeply
nested, are simple values, just like the number
3 or the character
\z. It doesn’t make sense to speak of “changing” the ...