Clojure core environment and runtime library providing a dynamic, general-purpose programming language on the JVM.
—
Comprehensive utilities for traversing, transforming, and navigating complex data structures through specialized namespaces: clojure.walk for tree traversal, clojure.datafy for data transformation, and clojure.zip for functional tree editing.
Generic tree traversal functions for recursively processing nested data structures.
(clojure.walk/walk inner outer form)
;; Core traversal function - applies inner to each element, then outer to result
;; inner: function applied to each sub-element
;; outer: function applied to reconstructed structure
;; form: data structure to traverse
;; Returns: transformed data structure
(clojure.walk/prewalk f form)
;; Pre-order traversal - calls f on each sub-form before recursing
;; f: transformation function
;; form: data structure to traverse
;; Returns: transformed data structure
(clojure.walk/postwalk f form)
;; Post-order traversal - calls f on each sub-form after recursing
;; f: transformation function
;; form: data structure to traverse
;; Returns: transformed data structure
(clojure.walk/prewalk-demo form)
;; Demonstrates prewalk behavior by printing each walked form
;; form: data structure to walk and print
;; Returns: original form (unchanged)
(clojure.walk/postwalk-demo form)
;; Demonstrates postwalk behavior by printing each walked form
;; form: data structure to walk and print
;; Returns: original form (unchanged)Higher-level transformation functions built on tree walking.
(clojure.walk/prewalk-replace smap form)
;; Pre-order replacement using substitution map
;; smap: map of {old-value new-value} replacements
;; form: data structure to transform
;; Returns: transformed data structure
(clojure.walk/postwalk-replace smap form)
;; Post-order replacement using substitution map
;; smap: map of {old-value new-value} replacements
;; form: data structure to transform
;; Returns: transformed data structure
(clojure.walk/keywordize-keys m)
;; Recursively transforms all map keys from strings to keywords
;; m: nested data structure containing maps
;; Returns: transformed structure with keyword keys
(clojure.walk/stringify-keys m)
;; Recursively transforms all map keys from keywords to strings
;; m: nested data structure containing maps
;; Returns: transformed structure with string keys
(clojure.walk/macroexpand-all form)
;; Recursively performs all possible macroexpansions in form
;; form: Clojure form potentially containing macros
;; Returns: fully macroexpanded formProtocol-based data transformation for converting objects to data representations.
(clojure.datafy/datafy x)
;; Attempts to return x as data using clojure.core.protocols/datafy
;; x: object to transform to data representation
;; Returns: data representation of x with metadata about original
(clojure.datafy/nav coll k v)
;; Returns possibly transformed v in context of coll and key k
;; coll: containing collection
;; k: key/index context (or nil)
;; v: value to potentially transform
;; Returns: transformed value via clojure.core.protocols/navFunctional tree editing with location-aware navigation and modification.
(clojure.zip/zipper branch? children make-node root)
;; Creates a new zipper structure for arbitrary trees
;; branch?: predicate fn - true if node can have children
;; children: fn returning seq of node's children
;; make-node: fn creating new branch node from existing node and children
;; root: root node of tree
;; Returns: zipper positioned at root
(clojure.zip/seq-zip root)
;; Returns zipper for nested sequences
;; root: root sequence
;; Returns: sequence zipper
(clojure.zip/vector-zip root)
;; Returns zipper for nested vectors
;; root: root vector
;; Returns: vector zipper
(clojure.zip/xml-zip root)
;; Returns zipper for XML elements (as from xml/parse)
;; root: root XML element
;; Returns: XML zipper(clojure.zip/node loc)
;; Returns the node at current location
;; loc: zipper location
;; Returns: node at location
(clojure.zip/branch? loc)
;; Returns true if node at location is a branch
;; loc: zipper location
;; Returns: boolean
(clojure.zip/children loc)
;; Returns seq of children of branch node at location
;; loc: zipper location (must be branch)
;; Returns: seq of child nodes
(clojure.zip/down loc)
;; Returns location of first child, nil if no children
;; loc: zipper location
;; Returns: child location or nil
(clojure.zip/up loc)
;; Returns location of parent, nil if at top
;; loc: zipper location
;; Returns: parent location or nil
(clojure.zip/left loc)
;; Returns location of left sibling, nil if none
;; loc: zipper location
;; Returns: left sibling location or nil
(clojure.zip/right loc)
;; Returns location of right sibling, nil if none
;; loc: zipper location
;; Returns: right sibling location or nil
(clojure.zip/leftmost loc)
;; Returns location of leftmost sibling
;; loc: zipper location
;; Returns: leftmost sibling location
(clojure.zip/rightmost loc)
;; Returns location of rightmost sibling
;; loc: zipper location
;; Returns: rightmost sibling location
(clojure.zip/next loc)
;; Returns next location in depth-first walk, nil if end
;; loc: zipper location
;; Returns: next location or nil
(clojure.zip/prev loc)
;; Returns previous location in depth-first walk, nil if beginning
;; loc: zipper location
;; Returns: previous location or nil(clojure.zip/path loc)
;; Returns seq of nodes leading to this location
;; loc: zipper location
;; Returns: seq of ancestor nodes
(clojure.zip/lefts loc)
;; Returns seq of left siblings of this location
;; loc: zipper location
;; Returns: seq of left sibling nodes
(clojure.zip/rights loc)
;; Returns seq of right siblings of this location
;; loc: zipper location
;; Returns: seq of right sibling nodes
(clojure.zip/root loc)
;; Returns root node of entire tree
;; loc: zipper location
;; Returns: root node
(clojure.zip/end? loc)
;; Returns true if location represents end of depth-first walk
;; loc: zipper location
;; Returns: boolean(clojure.zip/replace loc node)
;; Returns new location with node replaced
;; loc: zipper location
;; node: replacement node
;; Returns: new location with replaced node
(clojure.zip/edit loc f & args)
;; Returns location with node replaced by (apply f node args)
;; loc: zipper location
;; f: transformation function
;; args: additional arguments to f
;; Returns: new location with edited node
(clojure.zip/insert-left loc item)
;; Returns location with item inserted as left sibling
;; loc: zipper location
;; item: node to insert
;; Returns: new location
(clojure.zip/insert-right loc item)
;; Returns location with item inserted as right sibling
;; loc: zipper location
;; item: node to insert
;; Returns: new location
(clojure.zip/insert-child loc item)
;; Returns location with item inserted as leftmost child
;; loc: zipper location (must be branch)
;; item: node to insert
;; Returns: new location
(clojure.zip/append-child loc item)
;; Returns location with item inserted as rightmost child
;; loc: zipper location (must be branch)
;; item: node to insert
;; Returns: new location
(clojure.zip/remove loc)
;; Returns location with node removed
;; loc: zipper location
;; Returns: new location with node removedUsage Examples:
;; Tree walking examples
(require '[clojure.walk :as walk])
;; Transform all numbers in nested structure
(walk/postwalk
#(if (number? %) (* % 2) %)
{:a 1 :b [2 3 {:c 4}]})
;; => {:a 2, :b [4 6 {:c 8}]}
;; String keys to keyword keys
(walk/keywordize-keys {"a" 1 "b" {"c" 2}})
;; => {:a 1, :b {:c 2}}
;; Replace specific values
(walk/postwalk-replace {'old 'new :a :replaced}
'(old data (:a value) old))
;; => (new data (:replaced value) new)
;; Functional zipper examples
(require '[clojure.zip :as zip])
;; Navigate nested vector structure
(def data [[1 2] [3 [4 5]] 6])
(def z (zip/vector-zip data))
;; Navigate to deeply nested value
(-> z
zip/down ; into first level: [1 2]
zip/right ; to [3 [4 5]]
zip/down ; into [3 [4 5]]
zip/right ; to [4 5]
zip/down ; into [4 5]
zip/right ; to 5
zip/node) ; => 5
;; Edit nested structure
(-> z
zip/down ; to [1 2]
zip/right ; to [3 [4 5]]
zip/down ; into [3 [4 5]]
(zip/edit inc) ; change 3 to 4
zip/root) ; => [[1 2] [4 [4 5]] 6]
;; Add new elements
(-> z
zip/down ; to [1 2]
(zip/insert-right [7 8]) ; insert new vector
zip/root) ; => [[1 2] [7 8] [3 [4 5]] 6]
;; Tree traversal with zippers
(defn find-in-tree [pred z]
(loop [loc z]
(cond
(zip/end? loc) nil
(pred (zip/node loc)) loc
:else (recur (zip/next loc)))))
;; Find first even number
(let [z (zip/vector-zip [1 [2 3] [4 [5 6]]])]
(when-let [loc (find-in-tree even? z)]
(zip/node loc))) ; => 2
;; Data transformation with datafy
(require '[clojure.datafy :as d])
;; Transform exception to data
(try
(/ 1 0)
(catch Exception e
(d/datafy e)))
;; => returns map with exception details
;; Working with refs and atoms
(let [a (atom {:count 42})]
(d/datafy a)) ; => [{\count 42}] with metadataInstall with Tessl CLI
npx tessl i tessl/maven-org-clojure--clojure