This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-27
Channels
- # announcements (16)
- # architecture (19)
- # beginners (31)
- # calva (2)
- # cider (1)
- # clerk (4)
- # clj-yaml (58)
- # cljdoc (2)
- # cljs-dev (10)
- # clojure (77)
- # clojure-europe (108)
- # clojure-norway (26)
- # clojure-sanfrancisco (2)
- # conjure (1)
- # cursive (2)
- # datahike (5)
- # datomic (13)
- # emacs (7)
- # etaoin (3)
- # hyperfiddle (15)
- # introduce-yourself (3)
- # kaocha (1)
- # off-topic (21)
- # reagent (4)
- # releases (1)
- # shadow-cljs (41)
- # spacemacs (28)
- # specter (8)
- # squint (30)
- # yamlscript (2)
Hi, I want to do (what I think is) some advanced stuff in specter.
Basically make common navigators work with https://github.com/hoplon/javelin cells.
I started digging in and found that some navigators are basically a protocol, which is awesome cause that means if I just extend Cell
to implement them we're golden.
I just wanted to know if I'm on the right track or if anyone can give me some tips on how to go about it.
Thanks in advance 😁
starting to work on it and I'm having trouble with defnav
in cljs, probably macro related
@lidorcg Some of the navigators are based on protocols (e.g. ALL), others aren't. A navigator like keypath
works if the target object implements IPersistentMap
. But that's an interface, not a protocol, so you can't implement that after the fact.
After some digging I think I need to do some kind of wrapping to each navigator something like:
(select* [this structure next-fn]
((my-foo next-fn) structure))
But on each path.
I think higher order navigators like selected
or transformed
are what I need, am I on the right track? Where can I learn more about defining higher order navigators?You probably just want navigators specific to those data structures defined with defnav
Cell is a wrapping data structure like atom, the difference is while atom does deref and that's that, from there you continue normally, cells needs to propagate state so each navigation will also return cell:
(def x (cell {:list [{:n 5}{:n 3}...]}) => cell<{...}>
(def l ((formula get) x :list)) => cell<[...]>
((formula map) #((formula get) % :n) l) => cell<[5 3...]>
I think I can make the following work with transform and select:
(defnav
^{:doc "Navigates to atom value."}
CELL
[]
(sp/select* [this structure next-fn]
((formula next-fn) structure))
(sp/transform* [this structure next-fn]
(do
(swap! structure next-fn)
structure)))
I believe that that will bring me to:
(select [CELL :list CELL ALL CELL :n] x) => cell<[5 3 ...]>
From there I might be able to get to:
(select [(cell-nav :list ALL :n)] x) => cell<[5 3 ...]>
If you have any thoughts \ tips I'll be very thankful :)That looks like the right approach. Take a look at the definition of compact
which is similar to what you want to do with cell-nav
ok, I was able to define CELL:
(defnav
CELL
[]
(select* [this structure next-fn]
((maybe-formula next-fn) structure))
(transform* [this structure next-fn]
(do
(swap! structure next-fn)
structure)))
but on simple use-cases I already found a couple of issues:
(def x (cell {:a 1})) => [#object [javelin.core.Cell {:a 1}]]
(-> (sp/select [CELL :a] x)
(get 0)) => 1 ;; not a cell??
(swap! x #(assoc-in % [:a] 42)) =>
:repl/exception!
;
; Execution error (Error) at (<cljs repl>:1).
; conj! after persistent!
So I wasn't able to extract a simple value using CELL.
I am able to do the following because I extended cell to support lookup:
(def x (cell {:a 1})) => [#object [javelin.core.Cell {:a 1}]]
(def y (-> (sp/select [:a] x)
(get 0))) => #object [javelin.core.Cell 1]
(swap! x #(assoc-in % [:a] 42)) => {:a 42}
y => #object [javelin.core.Cell 42]
Another interesting phenomenon:
(-> (sp/select-any [CELL :a] x)) => #object[cljs.core.Reduced]
This is related to the fact that cell conceals it's data, and so unreduced doesn't "work" on them.
I came across this issue before, filtering and reducing on cells (when the outer process need to make a decision based on the value of the cell) isn't trivial.