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 (11)
- # 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.
Couldn’t you sort the locations in reverse order, start from the bottom doing the replacements upwards?
Interesting idea, it might work if I use the location search to go from the last one to the top one and assuming that changes in the bottom aren’t affecting positions above it.