Clojure 相当于试剂游标,用于更新嵌套映射和访问新值

问题描述 投票:0回答:2

我发现自己做了很多

(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 这似乎是我想要的,但可能有点矫枉过正?

谢谢,

syntax clojure
2个回答
1
投票

如果你专门写了很多

(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)))

你只需要像游标这样的库来做比这更复杂的事情。


0
投票

基于

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

接口还有其他几种方法,但您不必实现它们。

© www.soinside.com 2019 - 2024. All rights reserved.