Hi @nathanmarz my debugging led me to an interesting discovery 🧐
Here is a small replication:
first just the same as ATOM but prints on transform*
(defnav
^{:doc "Navigates to atom value."}
ATOM
[]
(select* [this structure next-fn]
(next-fn @structure))
(transform* [this structure next-fn]
(do
(println structure)
(swap! structure next-fn)
structure)))
now for the test:
(def travers-parents (sp/recursive-path [] p (sp/stay-then-continue [(sp/must :parent) p]))) ;; some tree traversal
(def specter-travers-test
{:parent {:state (atom "first")
:parent {:state (atom "second")}}})
(comment
(sp/setval [(sp/subselect [travers-parents (sp/must :state) ATOM]) sp/FIRST]
"changed"
specter-travers-test)
; #object[cljs.core.Atom {:val first}]
; #object[cljs.core.Atom {:val second}]
;;=> {:parent {:state #object [cljs.core.Atom {:val "changed"}], :parent {:state #object [cljs.core.Atom {:val "second"}]}}}
(sp/select [:parent :state ATOM] specter-travers-test)
;;=> ["changed"]
(sp/select [:parent :parent :state ATOM] specter-travers-test)
;;=> ["second"]
;;
)
So what I show here basically is that setval used on [(sp/subselect ...) sp/FIRST] actually seem to "touch" all the results of the subselect but in a way that doesn't change the value, but it does touch them.
This can be invisible if transform* doesn't have a side-effect.
Is this expected?yes, that's how it works