Clojure中如何用swap!替代reset!修改Atom中的单个元素
Using
swap! Instead of reset! for Incremental Atom Updates Great question! Switching to swap! here makes total sense—it’s built for incremental, atomic updates to atoms, which avoids manually dereferencing and resetting the entire structure like you do with reset!.
Here’s how you can rewrite your code to use swap! effectively:
;; Your existing setup (def structure (atom [{:id "an-id"} {:id "another-id"}])) (def job {:type "some-job"}) ;; The swap! version (swap! structure (fn [current-state] (map #(if (= "an-id" (:id %)) (update-in % [:performed-jobs] (fnil conj []) job) %) current-state)))
How this works:
swap!automatically grabs the current value of the atom (we named itcurrent-statehere) and passes it to your update function.- Your core logic stays identical: we iterate over each item, only modifying the entry with
:id "an-id"by appending the job to its:performed-jobsfield (usingfnilto safely handle cases where:performed-jobsdoesn’t exist yet). swap!then atomically updates the atom with the modified structure—no need for manual@structuredereferencing orreset!calls.
Bonus: Preserve vector type (optional)
Since map returns a sequence, if you want to keep the original vector structure instead of a sequence, use mapv instead:
(swap! structure (fn [current-state] (mapv #(if (= "an-id" (:id %)) (update-in % [:performed-jobs] (fnil conj []) job) %) current-state)))
This will give you the exact same end result as your original reset! approach:
[{:id "an-id" :performed-jobs [{:type "some-job"}]} {:id "another-id"}]
Now you’re using the idiomatic, concurrency-safe swap! instead of manually resetting the entire atom.
内容的提问来源于stack exchange,提问作者bpereira
相关产品推荐
相关产品推荐

