liveBook · Manning

Persistent vector

As explained in Clojure: The Essential Reference

A persistent vector is an immutable vector implementation that preserves older versions through structural sharing.

A persistent vector is an indexed Clojure collection that appears immutable while older versions remain available wherever they are still referenced. It is useful when code needs a changed vector without losing the previous value, or when cached results must support access by position. section 12.1 section 12.5

Updates do not copy the whole vector. Elements sit in the leaves of a balanced tree; changing one element copies its leaf and the nodes along the path to the root, while other nodes are shared. With 32-way branching, the tree stays shallow. An indexed change is O(log n) in theory but behaves almost like constant time in practice. section 12.1

Change a position, keep the old value

(def original [:a :b :c]) (def changed (assoc original 2 :d)) changed ; => [:a :b :d] original ; => [:a :b :c] (nth original 2) ; => :c (original 3) ; => IndexOutOfBoundsException section 12.1

Vectors work with sequence operations, but are not themselves sequence types: seq? returns false. Use vec to turn a seqable collection into a persistent vector; ordered inputs retain their order. For results that should remain vectors, mapv transforms elements and filterv retains those satisfying a predicate. Unlike map and filter, both produce their results eagerly rather than returning lazy sequences. section 12.1 section 12.5 section 12.8 section 12.9

Build vector-valued results

(vec '(:a 1 nil {})) ; => [:a 1 nil {}] (mapv inc [0 1 2 3]) ; => [1 2 3 4] (filterv odd? (range 8)) ; => [1 3 5 7] Choose map or filter instead when a vector result is unnecessary or laziness matters. section 12.5 section 12.8 section 12.9

One interoperability caveat qualifies the apparent immutability: vec may alias a Java object array of 32 or fewer elements. Do not mutate that array afterward, because the vector's observed contents may change. section 12.5

How Clojure: The Essential Reference covers it

How deep it goes
Explains path copying, 32-way branching, and update cost, but stops short of node-level implementation code.
Examples
Demonstrates indexed access and updates, Java-array conversion, and cached search-result pagination.
What it assumes
Assumes familiarity with Clojure collection functions while defining persistence and distinguishing vectors from sequences.
What you can do after
Apply it via Clojure core functions to preserve earlier values and produce indexed vector results.
How it connects
Relates persistent vectors to structural sharing, sequences, lazy sequences, and transducers.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.