更新包裹在原子内的 Clojure 映射

Update Clojure map that is wrapped inside an atom

我正在尝试更新原子内部的地图。每个地图都由一个值引用。

(def a (atom {}))

(defn foo [id mps]
  (let [x (merge (get mps id) mps)]
    (swap! a assoc id x) x))

(foo 2 {:baz 88}) => {:baz 88}

@a => {2 {:baz 88}}

(foo 2 {:bar 99}) => {:bar 99} ??

@a => {2 {:bar 99}} ??

它似乎正在覆盖而不是更新地图。我要查找的结果是:

(foo 2 {:baz 88}) => {:baz 88}

@a => {2 {:baz 88}}

(foo 2 {:bar 99}) => {:bar 99, :baz 88}

@a => {2 {:bar 99, :baz 88}}

任何帮助都会很棒

您正在用新值替换旧值(使用 assoc)。您正在寻找的是直接在原子上的 merge-with (http://conj.io/store/v1/org.clojure/clojure/1.7.0-alpha4/clj/clojure.core/merge-with/) 的行为。喜欢:

user=> (def a (atom {}))
#'user/a
user=> (swap! a #(merge-with merge % {:a {:b 1}}))
{:a {:b 1}}
user=> (swap! a #(merge-with merge % {:a {:c 2}}))
{:a {:c 2, :b 1}}