The solution proposed by @cgrant is excellent, but implicitly describes a tree, where all branches and leaf nodes have an associated value (key in the dictionary), except for the root node, which is just a branch without a value. Thus, the tree {"/" nil} not a tree with a single leaf node, but a tree with an anonymous root branch and a single leaf node with a value of / . In practice, this means that each tree walk must first perform (zip/down t) in order to go down to the root of the node.
An alternative solution is to explicitly model the root inside the map, i.e. create only zippers from cards with one key in the root. For example: {"/" {"etc/" {"hosts" nil}}}
The zipper can be implemented using:
(defn map-zipper [map-or-pair] "Define a zipper data-structure to navigate trees represented as nested dictionaries." (if (or (and (map? map-or-pair) (= 1 (count map-or-pair))) (and (= 2 (count map-or-pair)))) (let [pair (if (map? map-or-pair) (first (seq map-or-pair)) map-or-pair)] (zip/zipper (fn [x] (map? (nth x 1))) (fn [x] (seq (nth x 1))) (fn [x children] (assoc x 1 (into {} children))) pair)) (throw (Exception. "Input must be a map with a single root node or a pair."))))
mrucci
source share