`clojure.zip` provides zippers for navigating and functionally editing tree-shaped data. A zipper location holds a focus within a tree. Moving returns another location; `zip/node` returns the data at the focus. Edits produce a changed location without mutating the original tree. Call `zip/root` to obtain the resulting data; to navigate that result again, create a new zipper. section 8.4.4
Choose a constructor for the tree, then work with locations until the result is ready:
- Use `zip/vector-zip`, `zip/seq-zip`, or `zip/xml-zip` for their respective inputs. Use `zip/zipper` when the tree needs custom rules for identifying branches, finding children, and rebuilding nodes. section 8.4.4
- Use `zip/down`, `zip/up`, `zip/left`, and `zip/right` to move locally; `zip/leftmost` and `zip/rightmost` jump to the outermost sibling. `zip/children`, `zip/lefts`, and `zip/rights` retrieve data rather than locations. A move with nowhere to go can return `nil`. section 8.4.4
- Use `zip/replace` or `zip/edit` to change the focused node, `zip/remove` to delete it, and insertion functions to add siblings or children. Inserting a child at a leaf raises an exception. section 8.4.4
Edit a vector tree
`(require '[clojure.zip :as zip])` `(-> (zip/vector-zip [1 2 [3 4]]) zip/down zip/rightmost (zip/edit conj 5) zip/root)` ;; => [1 2 [3 4 5]] `zip/down` focuses the first child, `zip/rightmost` selects `[3 4]`, and `zip/edit` applies `conj` there. `zip/root` returns the complete edited vector. section 8.4.4
(defn custom-zip [root]
(zip/zipper ; #1
#(some-> % :node first map?) ; #2
(comp seq :node) ; #3
(fn [node children] ; #4
(assoc node :node (vec children)))
root)) ; #5
(def czip (custom-zip document)) ; #6
(-> czip zip/down zip/rightmost zip/down zip/node)
;; {:tag :checking, :meta nil, :node [90.11]}
A custom zipper supplies branch detection, child retrieval, and node reconstruction for a map-shaped tree; navigation then uses the same location functions. section 8.4.4
Unlike `clojure.walk`, a zipper does not require a depth-first traversal for every operation: navigate only the portion needed, or use `zip/next` and `zip/prev` for depth-first movement. For a whole-tree transformation, repeatedly process a location and advance with `zip/next` until `zip/end?`, then return `zip/root`. section 8.4.4
