我想更新一个简单的原子,比如:i
并返回新值,就像{:a 1}
一样,只有当给定键已经存在时(否则返回nil)。
这是我想出的最简单的解决方案:
swap!
但我不觉得它真的是原子的。在(defn cond-assoc [store k v]
(when (get @store k)
(swap! store assoc k v)))
和(get @store k)
操作之间可能发生很多事情。还有比这更好的解决方案吗?
答案 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)))