原子和条件映射更新

时间:2016-12-21 22:32:08

标签: clojure

我想更新一个简单的原子,比如:i并返回新值,就像{:a 1}一样,只有当给定键已经存在时(否则返回nil)。

这是我想出的最简单的解决方案:

swap!

但我不觉得它真的是原子的。在(defn cond-assoc [store k v] (when (get @store k) (swap! store assoc k v))) (get @store k)操作之间可能发生很多事情。还有比这更好的解决方案吗?

1 个答案:

答案 0 :(得分:5)

你是对的,你的解决方案不是很原子的。要进行原子交换,请创建一个仅在需要时转换地图的简单函数:

(defn assoc-if-exists [m k v]
  (if (m k) (assoc m k v) m))

请注意,这与原子或原子无关。要将它与原子一起使用,只需执行

(def store (atom {:a 1}))
(swap! store assoc-if-exists :a 4) ;; {:a 4}, value changed
(swap! store assoc-if-exists :b 4) ;; {:a 4}, nothing added

请注意,当密钥不存在时,这不会返回nil。如果您想要这种行为,可以检查返回的值是否包含密钥:

(defn atomic-assoc-or-nil [a k v]
  (let [r (swap! a assoc-if-exists k v)]
    (when (get r k) r)))