我发现自己做了很多
(get-in (swap! nested-map update-in [:a :b] update-fn) [:a :b])
更新一个新值,然后以原子方式访问它。这对我来说似乎有点笨拙 - 有没有更优雅的方式来做到这一点? reagent
有 cursor
的想法,一旦你定义了光标,上面的内容就变成了 (swap! cursor update-fn)
.
我发现 https://github.com/rlewczuk/clj-cursor 这似乎是我想要的,但可能有点矫枉过正?
谢谢,
如果你专门写了很多
(get-in (swap! m update-in ks f) ks)
,你显然可以自己将其定义为一个函数:
(defn swap-at-path! [m ks f & args]
(-> (apply swap! m update-in ks f args)
(get-in ks)))
你只需要像游标这样的库来做比这更复杂的事情。
clojure.lang.IAtom
界面实现您自己的光标非常简单:
(defn my-cursor [target-atom path]
(proxy [clojure.lang.IAtom] []
(swap [f] (get-in (swap! target-atom update-in path f) path))))
请注意,
clojure.lang.IAtom
可能被视为 Clojure 的实现细节,因此您是否要依赖它取决于您。
举个例子:
(def nested-map (atom {}))
(defn update-fn [x] (inc (or x 0)))
(def c (my-cursor nested-map [:a :b]))
(swap! c update-fn)
;; => 1
(deref nested-map)
;; => {:a {:b 1}}
IDeref
也可能有用:
(defn my-cursor [target-atom path]
(proxy [clojure.lang.IAtom clojure.lang.IDeref] []
(swap [f] (get-in (swap! target-atom update-in path f) path))
(deref [] (get-in (deref target-atom) path))))
接口还有其他几种方法,但您不必实现它们。