On 21 February 2010 09:37, Michael Wood <esiot...@gmail.com> 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 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