This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-06-02
Channels
- # announcements (11)
- # babashka (3)
- # beginners (54)
- # cherry (1)
- # cider (11)
- # clojure (28)
- # clojure-europe (1)
- # clojure-norway (4)
- # clojure-sweden (3)
- # clojurescript (40)
- # community-development (3)
- # cursive (12)
- # datomic (2)
- # emacs (6)
- # hyperfiddle (12)
- # missionary (14)
- # off-topic (13)
- # overtone (10)
- # re-frame (13)
- # releases (1)
- # ring (2)
- # specter (11)
- # tools-deps (7)
That's close to what I want. However, there's sometimes maps nested inside of vectors / list and I need to handle those too. So imagine data looks like this:
(def data
{:AThing {:AAThing [{:AABAThing 1} {:AABBThing 2} {:AABCThing 3}]
:A2Thing {:AAAThing "x"}}})
I'm not concerned about records or things like that for this use case. It's just all plain Clojure mapsThis seems to have the desired effect:
(def ALL-MAPS
(specter/recursive-path [] p
(specter/if-path map?
(specter/continue-then-stay specter/MAP-VALS p)
(specter/if-path (some-fn seq? vector? set? list?)
specter/ALL)
)))
(def data
{:AThing {:AAThing [{:AABAThing 1} {:AABBThing 2} {:AABCThing 3}]
:A2Thing {:AAAThing "x"}}})
(specter/transform [ALL-MAPS specter/MAP-KEYS] csk/->snake_case data)
Any reasons not to do it this way?it would be more elegant with cond-path
, but you have the right idea
Cool. Thank you!
I updated to use cond-path
, but it looks like the transformer isn't fully recursive.
(def ALL-MAPS
(specter/recursive-path [] p
(specter/cond-path
map? (specter/continue-then-stay specter/MAP-VALS p)
(some-fn seq? vector? set? list?) specter/ALL)))
(def data
{:AThing {:AAThing [{:AABAThing 1} {:AABBThing 2} {:AABCThing 3 :DeeplyNestedThing [{:ABC 1} {:ABC 2}]}]
:A2Thing {:AAAThing "x"}}})
(specter/transform [ALL-MAPS specter/MAP-KEYS] csk/->snake_case data)
Result is this:
{:a_thing {:aa_thing [{:aaba_thing 1} {:aabb_thing 2} {:aabc_thing 3, :deeply_nested_thing [{:ABC 1} {:ABC 2}]}],
:a_2_thing {:aaa_thing "x"}}}
What do I need to change for the maps in deeply_nested_thing
to be selected too?This seems to work:
(def ALL-MAPS
(specter/recursive-path [] p
(specter/cond-path
map? (specter/continue-then-stay specter/MAP-VALS p)
(some-fn seq? vector? set? list?) [specter/ALL p])))
(note the change to [specter/ALL p]
)
Is that the right way to do it? Why did the other way mostly work?I think you can change the some-fn
part to just sequential?
otherwise that looks right
or I suppose just replace seq?
, vector?
, and list?
with sequential?
I would also wrap the some-fn
part in pred
to make it higher performance, since otherwise Rama needs to determine how to convert the function to a navigator at runtime
Originally, I was going to use sequential?
, but I realized it didn't match for set. So I tried seqable?
but that had the unintended consequence of also matching strings. Using sequential?
with set?
works well.
Final product looks like this:
(def ALL-MAPS
(specter/recursive-path [] p
(specter/cond-path
map? (specter/continue-then-stay specter/MAP-VALS p)
(specter/pred (some-fn sequential? set?)) [specter/ALL p])))
Thanks for the help!