This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-03-13
Channels
- # announcements (14)
- # babashka (13)
- # beginners (25)
- # biff (7)
- # calva (36)
- # clj-kondo (22)
- # clojure (31)
- # clojure-austin (1)
- # clojure-europe (12)
- # clojure-losangeles (4)
- # clojure-nl (1)
- # clojure-norway (61)
- # clojure-uk (4)
- # clojurescript (3)
- # datomic (24)
- # events (1)
- # humbleui (9)
- # leiningen (9)
- # lsp (30)
- # malli (3)
- # missionary (15)
- # off-topic (5)
- # re-frame (4)
- # reitit (7)
- # releases (2)
- # remote-jobs (4)
- # rewrite-clj (8)
- # ring-swagger (2)
- # sci (6)
- # xtdb (2)
- # yamlscript (3)
Hi! If I understand correctly, every change I make to a zloc
is stored in that particular returned zloc
object. Is there a way to merge changes done to different zloc
s? For example, if I find several spots in the code where I want to apply changes and store separate zloc
s for them. Can I then use those zloc
s to apply changes and then combine the result? Otherwise, how can I get to the same zloc
location if I have a zloc
with changes and another zloc
of another location before the change was made?
Interesting, looks like clojure-lsp marks nodes by assigning them a custom ::markers
field and then it can get back to the marked nodes easily.
Hi @UHS6PHL31! The typical usage is to make all your changes while navigating through the zipper. Sometimes, it can be convenient to make a change, reparse, and then make a subsequent change. Let's contrive a simple code snippet:
{:a 1 :b 2}
Let's imagine you want to change 1
to :foo
and :b
to :bar
and add :c 3
.
Here's one way to do this in one pass
(require '[rewrite-clj.zip :as z])
(def s "{:a 1 :b 2}")
(-> s
z/of-string
z/down
z/right
(z/replace :foo)
z/right
(z/replace :bar)
z/up
(z/append-child :c)
(z/append-child 3)
z/root-string)
;; => "{:a :foo :bar 2 :c 3}"
Here's the same result but with re-parsing:
(-> s
z/of-string
z/down
z/right
(z/replace :foo)
z/root-string ;; take result
z/of-string ;; and reparse
z/down
z/right
z/right
(z/replace :bar)
z/root-string ;; take result
z/of-string ;; and reparse
(z/append-child :c)
(z/append-child 3)
z/root-string)
;; => "{:a :foo :bar 2 :c 3}"
When dealing with large source files, reparsing seems inefficient. Also navigating from one interesting spot to the next isn’t as trivial s calling z/right
. But possibly I can change my code to something more zipper friendly as currently I’m using (->> z (iterate z/next) (filter …) …
constructions which seems to only take original zloc
value into account..
Thanks for you help!
Yep, re-parsing is certainly not efficient enough for many use cases. But in a pinch, when you don't care about efficiency, it can be convenient.
Sometimes the prewalk
and postwalk
zip fns can work out nicely. I guess you'll have to play around to see what works for you. When you land on something that does work, feel free to come back and share; It could help others, too.
I’m currently trying an approach that uses loop [zloc .. data ...]
and z/find
.
Also https://github.com/clj-kondo/clj-kondo/tree/master/analysis can be super useful for locating items of interest for some use cases.