更新封装在原子中的Clojure映射



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

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

最新更新