On Fri, Jan 6, 2012 at 3:02 PM, Jozef Wagner <jozef.wag...@gmail.com> wrote:
> Consider this contrived piece of code:
>
> (def aval (atom {:dumped false :contents "hello world"}))
>
> (defn update!
>   [item]
>   (when-not (:dumped item)
>     (spit "a.out" (:contents item) :append true)
>     (assoc item :dumped true)))
>
> How should I correctly call update! ? Each of following two calls have
> drawbacks.
>
> (swap! aval update!) ;; update! can be called more than once
>
> (let [new-val (update! aval)]
>   ;; aval can be changed in between from other thread
>   (reset! aval new-val))
>
> Best,
> Jozef
>

Jozef,

I think you can solve this by adding a little more info and keeping
the update function and side effects separate:

(def aval (atom { :contents "hello world" }))

(defn update-item [{:keys [dumped] :as item}]
  (assoc item :dumped true :needs-dump (not dumped)))

(let [{:keys [needs-dump contents]} (swap! aval update-item)]
  (if needs-dump
    (spit "a.out" contents :append true)))

Whoever gets to aval first while it hasn't been dumped will see
needs-dump as true and write the file. Depending on your requirements,
if the file write fails, you'll might need to do some extra work to
put aval back in a state consistent with reality.

Hope this helps,

Dave

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to