On 21 February 2010 09:37, Michael Wood <[email protected]> wrote:
> (defn print-info []
> (let [[src dst] (dosync
> (ensure source-account)
> (ensure dest-account)
> �...@source-account @dest-account])]
> (println src)
> (println dst)))
This can be simplified to
(defn print-info []
(let [[src dst] (dosync
[(ensure source-account)
(ensure dest-account)])]
(println src)
(println dst)))
ensure returns the in-trasaction value of the ref.
There's no guarantee that the refs won't be changed a split second
after the transaction, of course...
To demonstrate the difference between a simple @r and (ensure r) in a
transaction, define the following ref & function at the REPL:
(def r (ref 1))
(defn funk [r]
(dosync
(let [v (ensure r)]
(println v)
(Thread/sleep 5000)
(println v))))
Now launch it in a separate thread:
(.start (Thread. #(funk r)))
It'll print a "1" straight away, but you'll have a moment to type in
another expression before it proceeds with the second println. So, do
this:
(dosync (ref-set r 5))
Notice that this blocks until the second println happens, then resets
the value of the ref afterwards.
With (ensure r) replaced by @r in the definition of funk, the (dosync
(ref-set r 5)) would succeed and the funky transaction would retry,
thus performing three printlns in total.
Thus using ensure may actually make in-transaction side-effects safe
at the cost of some lost concurrency.
Sincerely,
Michał
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en