I use specter to manipulate my state object in the front end. I’m curious: is there a way to apply multiple specter transformations to an atom atomically? If I were doing this with the normal swap!
function I’d just wrap all the transformations in a fn
. But I’m not sure how to do that with specter. (I’m asking because I’m worried that applying multiple specter transformations to a reagent atom might cause me grief, given that components get re-rendered in response to updates. So far, I’m not 100% this is a real problem, because I think reagent batches updates, but I’m still curious.)
@lee.justin.m yes you can use multi-transform
for that
e.g. (multi-transform [ATOM (multi-path [:a (terminal inc)] [:b (terminal dec)])] state-object)
@nathanmarz super thanks!
oh i hadn’t seen this list-of-macros page. there are all kinds of goodies here.
definitely worth skimming through the wiki
it's mostly up to date nowadays
@nathanmarz Just following up on the example you just used in #clojure, could you explain this:
(def data
{:a [:x :y]
:b [:x :y]})
(select [ALL (collect-one FIRST) LAST] data)
;; -> [[:a [:x :y]] [:b [:x :y]]]
;; The next statement will distribute the :a and :b
(select [ALL (collect-one FIRST) LAST ALL] data)
;; -≥ [[:a :x] [:a :y] [:b :x] [:b :y]]
;; But this, which applies the same selector to the intermediate result, does not
(select [ALL] [[:a [:x :y]] [:b [:x :y]]])
;; -> [[:a [:x :y]] [:b [:x :y]]]
@justinlee collecting variables is a special thing, search for “collect” in the readme for an explanation: https://github.com/nathanmarz/specter
@schmee thanks yea i read that and the docs for collect
and collect-one
but i can’t for the life of me figure out how they alter the ALL
selector in the context of a select
there is some reference to adding a value to the ‘collected values’ but I haven’t seen how the collected values are used in selectors like ALL
(though I understand how they are used in the transform
example when you need an argument to the transforming function
user=> (select [ALL (collect-one FIRST) LAST] data)
[[:a [:x :y]] [:b [:x :y]]]
user=> (select [ALL (collect-one FIRST) (collect-one FIRST) LAST] data)
[[:a :a [:x :y]] [:b :b [:x :y]]]
looks to me like select
just calls vector
on the collected arguments + the value(s) you’ve navigated to
Yea I guess that’s it. I’m not sure why it does that. 🙂
com.rpl.specter=> (select [(putval "a") ALL] [1 2 3])
[["a" 1] ["a" 2] ["a" 3]]
com.rpl.specter=> (select [(putval "a") FIRST] [1 2 3])
[["a" 1]]
com.rpl.specter=> (select [(putval "a") (putval "b") ALL] [1 2 3])
[["a" "b" 1] ["a" "b" 2] ["a" "b" 3]]
@lee.justin.m this is the code that creates that behavior: https://github.com/nathanmarz/specter/blob/master/src/clj/com/rpl/specter/impl.cljc#L294
got it thanks. that makes sense.