我有一个原子,它有两个部分。
(def thing (atom {:queue '() :map {}}))
我想更新:queue和:map in one atomic,以防止它们脱离同步。
(swap! thing update-in [:queue] (list 1))
(来自这个问题:How to append to a nested list in a Clojure atom?)
(swap! thing assoc-in [:map 1] (:key :value))
(来自这个问题:Using swap to MERGE (append to) a nested map in a Clojure atom?)
如何在单个交换语句中执行这些操作? (假设这会阻止他们脱离同步?)
答案 0 :(得分:10)
你想做一个改变,对吗?你可以把这个改变写成纯粹的功能吗?您需要做的就是编写该函数,并将其作为参数传递给swap!
。
(defn take-from-queue [{q :queue, m :map}]
{:queue (rest q), :map m (assoc m :new-task (first q))})
(swap! thing take-from-queue)
我当然不知道你真正希望你的函数体是做什么的,所以我已经编造了一些不会抛出异常的东西。
答案 1 :(得分:1)
假设你有一个哈希映射原子:
(def m1 (atom {:a "A" :b "B"}))
要同时更改:a
和:b
,将其值更改为不同的值(例如数字1和2),请使用此函数:
(defn my-swap! [params]
(swap! m1 (fn [old new] new) params))
,像这样:
(my-swap! {:a 1 :b 2}) ;=> {:a 1, :b 2}
使用以下功能和执行可以实现相同的效果:
(defn my-multi-swap! [params1 params2]
(swap! m1 (fn [old new1 new2] new2) params1 params2))
(my-multi-swap! {} {:a 1 :b 2}) ;=> {:a 1, :b 2}
如果要忽略旧值,通常会使用reset!
。我们在这里使用它:
(defn my-merge-swap! [params]
(swap! m1 (fn [old new] (merge old new)) params))
(my-merge-swap! {:b 3}) ;=> {:a "A", :b 3}
交换的第一个参数! function 是atom的现有值,您必须传入一个或多个额外参数,您可以使用这些参数为atom赋予其新值。