I have a nested structure, combining vectors and maps like this:
[{:__type "some_type"
:mykey 1
:date #inst"..."
:subs [{__type "another_type"
:typekey "value"}
{__type "another_type"}]
:onesub {:__type "random_type"
:subkey 2}]}
What I would like to do is tranform some keys of all maps of a certain type (the transformation is always the same). So, for example, what I would like to do something like (with the previous map as m
):
(resolve-values {"some_type" [:date :name] "random_type" [:another_key]} m)
which would transform all :date
and :name
values of maps which have a :__type "some_type"
entry and all :another_key
values of maps which have a :__type "random_type
entryhow would I do that using specter
(I guess specter is the best way to do it π )
it has to be some recursive path, but I can't really figure out how it would look like, so:
(specter/transform [....?] resolve m)
with resolve
the function to apply to the values that have to be transformed, but what is ...?
?
so, this is what I came up with so far for one type:
(defn type-map-path [__type]
(specter/recursive-path [] p
[(specter/walker #(= (:__type %) __type))
(specter/stay-then-continue [specter/ALL p])]))
(def SOME-TYPE-MAP-PATH (type-map-path "some_type"))
(def SOME-TYPE-KEYS-PATH (specter/multi-path :date :name))
Just wondering looping and walking several times would bring much benefit over trying to make multi-path
work for different __type
s
@kurt-o-sys this is a better way to do it:
(def MAPS
(recursive-path [] p
(cond-path
map? (continue-then-stay MAP-VALS p)
coll? [ALL p])
))
(transform [MAPS #(= (:__type %) "another_type")] resolve data)
walker
is very wasteful in this case, since it traverses into map keys and key/value pairs
this is a much more efficient way to navigate your data structure that leverages the structure of your data
oh, nice, thx!
I'm starting to really fall in love with specter π
Hi everyone. I'm trying to add Specter to a lein clojure project. I've added [com.rpl/specter "1.1.0"]
to my dependencies and (:require [com.rpl.specter])
to my ns. I'm getting the following error in my ns thought: FileNotFoundException Could not locate com/rpl/specter__init.class or com/rpl/specter.clj on classpath. clojure.lang.RT.load (RT.java:463)
.
@yogidevbear are you in a REPL?
I'm working from within ProtoREPL doing inline evaluation inside atom io
okay, I donβt know how that works unfortunately
try running lein deps
inside your project and see if that helps
No luck
@yogidevbear you're best off asking in #clojurescript
Hmmm, but I'm not using ClojureScript
oh sorry, misunderstood
does it work from lein repl
?
Yup, seems to work if I do (use 'com.rpl.specter)
from within lein repl
have you tried restarting protorepl?
I'll give that a try
would it be worth clearing out my .m2
folder too?
doubtful given that it's working with a regular repl
Fair point π