specter

Latest version: 1.1.3
2018-02-21T11:48:21.000051Z

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"}.

schmee 2018-02-21T13:26:12.000126Z

@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"}]}

schmee 2018-02-21T13:26:52.000321Z

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

schmee 2018-02-21T13:28:50.000139Z

also, replace-in might be of help: https://github.com/nathanmarz/specter/wiki/List-of-Macros#replace-in

schmee 2018-02-21T13:31:21.000378Z

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

souenzzo 2018-02-21T13:36:03.000171Z

@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

2018-02-21T13:48:16.000361Z

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

schmee 2018-02-21T13:49:34.000270Z

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

schmee 2018-02-21T13:51:05.000334Z

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

schmee 2018-02-21T13:51:23.000454Z

vs

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

2018-02-21T13:54:02.000360Z

Now I see, thank you! 🙂

johanatan 2018-02-21T19:51:10.000461Z

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?

nathanmarz 2018-02-21T19:53:09.000178Z

@johanatan you can use the submap navigator for that

johanatan 2018-02-21T19:53:20.000174Z

ah, ok. thx

spieden 2018-02-21T22:44:16.000086Z

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

1