Fork me on GitHub
#specter
<
2018-02-21
>
Nikolay Artamonov11:02:21

Hi all! Is it possible to get removed (via NONE) element, for example:

(sr/setval [:elems
            (sr/filterer (sr/must :id) (sr/pred= 1))
            sr/FIRST] sr/NONE {:elems [{:id 1 :name "A"} {:id 2 :name "B"}]})
=> {:elems [{:id 2, :name "B"}]}
I want to get not only whole structure but also removed one: {:id 1 :name "A"}.

schmee13:02:12

@nartamonov you can use transform instead, like this:

user=> (sr/transform
  #_=>  [:elems (sr/filterer (sr/must :id) (sr/pred= 1)) sr/FIRST]
  #_=>  (fn [x] (println x) sr/NONE)
  #_=>  {:elems [{:id 1 :name "A"} {:id 2 :name "B"}]})
{:id 1, :name A}
{:elems [{:id 2 :name "B"}]}

schmee13:02:52

if you return NONE from the transformation function it will remove the element just like setval

schmee13:02:21

actually, replace-in is perfect:

user=> (sr/replace-in
  #_=>  [:elems (sr/filterer (sr/must :id) (sr/pred= 1)) sr/FIRST]
  #_=>  (fn [x] [sr/NONE x])
  #_=>  {:elems [{:id 1 :name "A"} {:id 2 :name "B"}]})
[{:elems [{:id 2 :name "B"}]} ([:id 1] [:name "A"])]

souenzzo13:02:03

@nartamonov path works equally in select and setval, so you can do something like it:

(let [data {:elems [{:id 1 :name "A"} {:id 2 :name "B"}]}
      path [:elems ALL (if-path [:id #{1}] STAY)]]
  {:data    (setval path NONE data)
   :removed (select path data)})
replace-in is a option too

Nikolay Artamonov13:02:16

@schmee Thanks, it works almost as I want. If instead x we use [x] then we'll get exactly the same structure (hashmap) that was removed:

(sr/replace-in
    [:elems (sr/filterer (sr/must :id) (sr/pred= 1)) sr/FIRST]
    (fn [x] [sr/NONE [x]])
    {:elems [{:id 1 :name "A"} {:id 2 :name "B"}]})
=> [{:elems [{:id 2, :name "B"}]} ({:id 1, :name "A"})]
Though, don't understand why...

schmee13:02:34

ahh, sorry, I missed that the hash map changed into a seq, good that you found the solution

schmee13:02:05

the reason is that the second element in the vector gets added to a sequence of return values, so if you have just a hash map it will be changed into a seq first, ie:

user=> (seq {:id 1, :name "A"})
([:id 1] [:name "A"])

schmee13:02:23

vs

user=> (seq [{:id 1, :name "A"}])
({:id 1 :name "A"})

Nikolay Artamonov13:02:02

Now I see, thank you! 🙂

johanatan19:02:10

hi, is it possible to specter/transform a k/v pair in a map to another map and then have that merged with the original siblings?

nathanmarz19:02:09

@johanatan you can use the submap navigator for that

spieden22:02:16

was just reaching for clojure.walk and learned recursive-path and cond-path instead — wasn’t disappointed =)