I want to write a function for a zipper that removes all right siblings of a node while staying at the same location.
(defn remove-all-rights-1 [loc]
(if (zip/right loc)
(recur (zip/remove (zip/right loc)))
loc))
The problem here is that remove returns the location that would have preceded the current node in DFS.
Therefore the following example...
(-> (clojure.zip/vector-zip [1 [[2] 3]])
(zip/down)
(zip/right)
(zip/down)
(remove-all-rights-1)
(zip/replace :x)
(zip/root))
...gives [1 [[:x]]]
instead of [1 [:x]]
because zip/remove
jumped to the bottom leaf instead of just going back left.
How should I remove the right siblings without also changing location in the tree? Thanks in advance!
(letfn [(kill-right [loc]
(let [lost (zip/rights loc)
parent (-> loc zip/up zip/node)
node (into (empty parent) (take (- (count parent) (count lost)) parent))]
(-> loc
zip/up
(zip/replace node)
zip/down
zip/rightmost)))]
(-> (clojure.zip/vector-zip [1 [[2] 3]])
zip/down
zip/right
zip/down
kill-right
(zip/replace :x)
zip/root))