rewrite-clj

2023-11-18T04:48:57.570269Z

if i have a form with lots of nested values and i want to gather all of the nodes that match some predicate, how do i do that? there's no tree-seq, and pre/post walk work like in clojure, and the various find-next-* functions don't seem to go up unless i misread the docstring.

lread 2023-11-18T14:14:22.033199Z

Hi again @nbtheduke! Here's what I came up with:

(require '[rewrite-clj.node :as n]
         '[rewrite-clj.zip :as z])

(def some-code "(let [x {:a 1 :b 2 :c {:d {:e 3}}}])")

(def zloc (z/of-string some-code))

;; an example of a predicate
(defn keyword-node? [zloc]
  (some-> zloc z/node n/keyword-node?))

;; little helper to find the way we'd like to
(defn find-pred [p? zloc]
  ;; use z/next to include all nodes
  (z/find-next zloc z/next p?))

(->> zloc
     z/up ;; start from root
     (find-pred keyword-node?) ;; move to first match
     (iterate #(find-pred keyword-node? %)) ;; iterate over all other matches
     (take-while #(not (z/end? %))) ;; until we reach the end
     (map z/string)) ;; and convert zloc as you see fit
;; => (":a" ":b" ":c" ":d" ":e")
How's that work for you?

2023-11-18T15:10:30.328919Z

Oh interesting, so from the root, you step into each top level form and dive until your reach the end

2023-11-18T15:12:14.857859Z

I wonder if this could be generalized into a “tree-seq”

2023-11-18T15:12:27.073159Z

Thank you! I’ll give this a go and see how it works for me

lread 2023-11-18T17:05:06.664839Z

Cool, come on back if you have more questions!