A transient is a temporary mutable form of a Clojure vector, map, or set. It helps when many updates are needed to construct a collection but callers only need the final persistent result. Create one with `transient`, perform the updates, then convert it with `persistent!`. section 20.1
During the transient phase:
- Use mutating operations such as `assoc!`, `conj!`, and `dissoc!` instead of their persistent-collection counterparts. Some reads, including `get` and `count`, still work. section 20.1
- Pass each update’s returned transient to the next update. Repeatedly updating an older reference can produce an incomplete result. section 20.1
Build a map with batched updates
`(let [m (reduce (fn [m k] (assoc! m k k)) (transient {}) (range 20))] (count (persistent! m)))` returns `20`. Here, `reduce` carries each returned transient forward before `persistent!` produces the final map. section 20.1
(import 'java.util.HashMap)
(def transient-map (transient {}))
(def java-map (HashMap.))
(dotimes [i 20] ; #1
(assoc! transient-map i i)
(.put java-map i i))
(persistent! transient-map) ; #2
;; {0 0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7}
(into {} java-map) ; #3
;; {0 0, 7 7, 1 1, 4 4, 15 15, 13 13, 6 6,
;; 3 3, 12 12, 2 2, 19 19, 11 11, 9 9, 5 5,
;; 14 14, 16 16, 10 10, 18 18, 8 8, 17 17}
This contrasting example ignores the return value of `assoc!`: after 20 attempted insertions, the resulting persistent map contains only the first eight entries. section 20.1
Keep the mutable phase explicit. A transient is not an `into` destination, and ordinary `conj` does not work on it. For routine collection construction, functions such as `into` and `frequencies` already use transients internally; reach for a transient directly when managing the update loop yourself. section 20.1 section 8.1.1
