Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Clojure by

It can be useful to attach arbitrary metadata to a zipper.

When doing so, this metadata is preserved, as far as I can tell, by all zipper operation that return a zipper, except when the end state is reached.

I studied the behaviour with the following code:

(def res
  (let [zloc (vary-meta (czip/vector-zip [1 2 3])
                        assoc :my-app/my-thing 42)
        ops [["down" czip/down]
             ["up" czip/up]
             ["down" czip/down]
             ["right" czip/right]
             ["left" czip/left]
             ["rightmost" czip/rightmost]
             ["leftmost" czip/leftmost]
             ["next" czip/next]
             ["prev" czip/prev]
             ["up" czip/up]
             ["append-child" #(czip/append-child % "append-child")]
             ["down" czip/down]
             ["edit" #(czip/edit % str "-edit")]
             ["up" czip/up]
             ["insert-child" #(czip/insert-child % "insert-child")]
             ["down" czip/down]
             ["right" czip/right]
             ["insert-left" #(czip/insert-left % "insert-left")]
             ["insert-right" #(czip/insert-right % "insert-right")]
             ["rightmost" czip/rightmost]
             ["remove" czip/remove]
             ["replace" #(czip/replace % "replace")]
             ["rightmost" czip/rightmost]
             ["next past last node" czip/next]]]
    (->> (reductions (fn [zloc [_desc f]] (f zloc))
         (map vector (into [["--" "--"]] ops))
         (map (fn [[[desc _f] zloc]]
                {:op-desc desc
                 :end? (czip/end? zloc)
                 :node (czip/node zloc)
                 :root (czip/root zloc)
                 :my-meta (some-> zloc meta :my-app/my-thing)
                 :meta (meta zloc)})))))

If I then search the result:

(filter #(or (:end %)
             (nil? (:my-meta %))
             (nil? (:meta %)))
;; => ({:op-desc "next past last node",
;;      :end? true,
;;      :node ["insert-child" "insert-left" "1-edit" "insert-right" 2 "replace"],
;;      :root ["insert-child" "insert-left" "1-edit" "insert-right" 2 "replace"],
;;      :my-meta nil,
;;      :meta nil})

As you can see, it looks like all operations preserve my arbitrary metadata except when the returned zipper is in an end state.

There's no value to dumping the full results from above, but let's look at an arbitrary single result, just to show what things look like when we are not in the zipper end state:

(nth res 11)
;; => {:op-desc "append-child",
;;     :end? false,
;;     :node [1 2 3 "append-child"],
;;     :root [1 2 3 "append-child"],
;;     :my-meta 42,
;;     :meta
;;     {:zip/branch? #function[clojure.core/vector?--5431],
;;      :zip/children #function[clojure.core/seq--5419],
;;      :zip/make-node #function[clojure.zip/vector-zip/fn--9351],
;;      :my-app/my-thing 42}}

Please log in or register to answer this question.