Fork me on GitHub
#specter
<
2017-05-31
>
danboykis00:05:56

If I have the following:

(def person
  [{:name "Person", :id 1, :job "Something", :tag :a}
   {:name "Person", :id 1, :job "Something", :tag :b}
   {:name "Person", :id 1, :job "Something", :tag :c}])
I want to transform that to
{:name "Person", :id 1, :job "Something", :tag #{:c :b :a}}
In plain clojure I can do it with
(into {} (map (fn [[k v]] (assoc k :tag v)))
      (reduce (fn [accum e]
          (let [sm (select-keys e [:name :id :job])]
            (if-let [exists (get accum sm)]
              (assoc accum sm (conj exists (:tag e)))
              (assoc accum sm #{(:tag e)}))))
        {}
        person))
I am hoping there's a nicer way to do the same in specter

nathanmarz02:05:01

@danboykis that's computing an entirely new value, whereas specter is about changing part of a data structure

nathanmarz02:05:39

there are pieces of it you can make nicer with specter, like replacing the if-let clause with (setval [(keypath sm) NONE-ELEM] (:tag e) accum)

danboykis03:05:22

@nathanmarz thanks for the explanation, I am new to specter and don't have a good feel for the its use cases yet

mping06:05:06

@nathanmarz figured it out: (specter/select (specter/walker is-pdf-attachment?) user/msg)