On Jan 6, 7:32 pm, Cedric Greevey <cgree...@gmail.com> wrote: > On Fri, Jan 6, 2012 at 10:22 PM, Alan Malloy <a...@malloys.org> wrote: > > On Jan 6, 6:16 pm, Cedric Greevey <cgree...@gmail.com> wrote: > >> On Fri, Jan 6, 2012 at 4:34 PM, Alan Malloy <a...@malloys.org> wrote: > >> > On Jan 6, 12:56 pm, Jozef Wagner <jozef.wag...@gmail.com> wrote: > >> >> Thank you, > > >> >> But the things are more complicated. In my case, I need to update the > >> >> atom > >> >> with the result of a (native) function which unfortunately also performs > >> >> some side effects and cannot be split in two. > > >> >> Updated example: > > >> >> (def state {:result nil :input [1 2 3]}) > > >> >> (defn update-item! > >> >> [item] > >> >> (if (:result item) ; if already processed, do nothing > >> >> item > >> >> (let [result (side-effect-fn! (:input item))] > >> >> (assoc item :result result)))) > > >> >> (swap! state update-item!) ;; same problem > > >> > Not doable with atoms if you have a side-effecty thing that you can't > >> > separate out. You'll have to use something lower-level like Java > >> > synchronization or locks. > > >> Or something higher level like transactions. Use a ref and have > >> update! alter the ref, then (send-off some-agent #(spit ...)), inside > >> a dosync. The agent send only goes if the transaction commits. > > > This works exactly as well as with atoms: it works fine if you have a > > pure function and an I/O function, but doesn't work if you have a > > single function that does both pure computation and I/O side effects. > > Jozef has some Java magic that does I/O as a side effect of a > > computation, and he cannot untangle the two. > > Wrong. Jozef has this: > > (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))) > > (swap! aval update!) > > Which can be transformed to this: > > (def aval (ref {:dumped false :contents "hello world"})) > > (def aagent (agent nil)) > > (defn update > [item] > (dosync > (if (:dumped @item) > (ref-set item nil) > (do > (alter item assoc :dumped true) > (send-off aagent (fn [_] (do (spit "a.out" (:contents @item) > :append true) nil))))))) > > (update aval) > > which should have the same semantics, except that the spit cannot be > done twice (or more) for one call to update.
That's the simplification he made in his first post, but if you look at the post I was actually replying to he's confessed he actually has a different situation. -- 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