How do I update a vector element of an atom in Clojure?

孤街醉人 提交于 2020-01-02 05:47:20

问题


I have a vector atom and I want to update an entry that is itself a map.

(def vector-atom (atom []))
(swap! vector-atom conj { :id 1 :name "myname" })

How would I go about updating only this member?

In the mindset of mutable Java land, I would do something like this:

(defn find-by-id [id]
  (first (filter (fn [entry] (= (:id entry) id))
         @vector-atom)))

(defn update-entry [id new-entry]
  (let [curr-entry (find-by-id id)
        merged-entry (merge curr-entry new-entry)]
    ###set the curr-entry to merged-entry###))

回答1:


If the indices of the vector correspond to :ids, you can use something like

(swap! vector-atom update-in [id] merge new-entry)

If they don't, then you have two options: (1) use a map of id -> map instead of a vector and the above simple solution, (2) use a vector and something like the following:

(swap! vector-atom
       (fn [v]
         (let [i (find-index-of-entry v)]
           (assoc v i (merge (nth v i) new-entry)))))

find-index-of-entry could be a simple linear scan of the vector or, if the items are ordered by :id, a binary search. A linear scan will of course be dreadfully inefficient for longer vectors (and so if the vectors might be longer, switching to maps as per (1) above is a solution deserving of consideration).



来源:https://stackoverflow.com/questions/21772671/how-do-i-update-a-vector-element-of-an-atom-in-clojure

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!