specter

Latest version: 1.1.3
2018-02-24T07:06:06.000029Z

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 entry

2018-02-24T07:06:44.000050Z

how would I do that using specter (I guess specter is the best way to do it πŸ™‚ )

2018-02-24T07:07:49.000040Z

it has to be some recursive path, but I can't really figure out how it would look like, so: (specter/transform [....?] resolve m)

2018-02-24T07:08:22.000017Z

with resolve the function to apply to the values that have to be transformed, but what is ...??

2018-02-24T13:46:35.000057Z

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))

2018-02-24T13:47:38.000094Z

Just wondering looping and walking several times would bring much benefit over trying to make multi-path work for different __types

nathanmarz 2018-02-24T14:39:26.000041Z

@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)

nathanmarz 2018-02-24T14:40:01.000090Z

walker is very wasteful in this case, since it traverses into map keys and key/value pairs

nathanmarz 2018-02-24T14:40:19.000042Z

this is a much more efficient way to navigate your data structure that leverages the structure of your data

2018-02-24T14:49:26.000059Z

oh, nice, thx!

2018-02-24T15:44:08.000142Z

I'm starting to really fall in love with specter πŸ˜›

yogidevbear 2018-02-24T21:25:01.000079Z

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).

schmee 2018-02-24T21:29:27.000074Z

@yogidevbear are you in a REPL?

yogidevbear 2018-02-24T21:39:15.000008Z

I'm working from within ProtoREPL doing inline evaluation inside atom io

schmee 2018-02-24T21:49:53.000047Z

okay, I don’t know how that works unfortunately

schmee 2018-02-24T21:50:03.000030Z

try running lein deps inside your project and see if that helps

yogidevbear 2018-02-24T21:51:19.000037Z

No luck

nathanmarz 2018-02-24T21:51:19.000093Z

@yogidevbear you're best off asking in #clojurescript

yogidevbear 2018-02-24T21:51:38.000070Z

Hmmm, but I'm not using ClojureScript

nathanmarz 2018-02-24T21:52:06.000071Z

oh sorry, misunderstood

πŸ™‚ 1
nathanmarz 2018-02-24T21:52:23.000022Z

does it work from lein repl?

yogidevbear 2018-02-24T21:55:22.000052Z

Yup, seems to work if I do (use 'com.rpl.specter) from within lein repl

nathanmarz 2018-02-24T21:55:39.000066Z

have you tried restarting protorepl?

yogidevbear 2018-02-24T21:56:24.000041Z

I'll give that a try

yogidevbear 2018-02-24T21:56:39.000088Z

would it be worth clearing out my .m2 folder too?

nathanmarz 2018-02-24T21:57:48.000082Z

doubtful given that it's working with a regular repl

yogidevbear 2018-02-24T22:00:05.000133Z

Fair point πŸ™‚