I think I'm right.  This is a program that demonstrates what I was thinking
o:

;; Program begins.

(defn traverse [f dat]
  (vec (map #(f %) dat)))

(def data (traverse ref (take 10 (iterate inc 0))))

(-> (fn []
      (dosync (loop [i 0
                     data data]
                (when (seq data)
                  (Thread/sleep 1000)
                  (println (str ">>> " i ": " @(first data)))
                  (recur (+ i 1) (next data))))))
    Thread.
    .start)

(Thread/sleep 1500)
(dosync
 (traverse (fn [ref]
             (alter ref inc))
           data))

(Thread/sleep 1000)
;; This one extra sleep forces the "main" thread sleeping for one
;; second.  Due to some reason I don't know for now, when `dosync'
;; retries, the first sleep will be interrupted.
(Thread/sleep 1000)
(dosync
 (traverse (fn [ref]
             (alter ref inc))
           data))

(traverse #(println (str "--- " @%)) data)

;; Program ends here.

The result is

>>> 0: 0
>>> 0: 1
--- 2
--- 3
--- 4
--- 5
--- 6
--- 7
--- 8
--- 9
--- 10
--- 11
>>> 1: 2
>>> 0: 2
>>> 1: 3
>>> 2: 4
>>> 3: 5
>>> 4: 6
>>> 5: 7
>>> 6: 8
>>> 7: 9
>>> 8: 10
>>> 9: 11

Meaning the `dosync' form in the thread is retried twice, due to the two
passes of changing of the values in `data'.  So using `dosync' to surround
the whole data structure is the best way to go.

Best regards,
Guanpeng Xu

On Tue, Jan 31, 2012 at 12:00 PM, Herbert Euler <herberteu...@gmail.com>wrote:

> Hmm, I didn't read the definition of `board-map' carefully.  It seems the
> second form
>
>    (dosync (board-map deref board))
>
> is the best among the three, as it views `board' as a whole.  The other
> two might have the potential problem of printing incoordinated values of
> entries in `board', i.e. the entries of `board' might change during the
> iteration in the `map' form. Am I right?
>
> Thanks,
> Guanpeng Xu
>
> On Tue, Jan 31, 2012 at 11:46 AM, Guanpeng Xu <herberteu...@gmail.com>wrote:
>
>> Hi all,
>>
>> In section 11.2.1 of the book /The Joy of Clojure/, the author shows
>> the effect of
>> `dosync' by starting 100 threads and then watching the value of a Ref:
>>
>>  (go make-move 100 100)
>>  (board-map #(dosync (deref %)) board)
>>
>> Here, the first `go' form starts 100 threads, their effect is
>> modifying `board' using
>> `dosync' and `alter'.  `board-map' is defined as
>>
>>  (defn board-map [f bd]
>>    (vec (map #(vec (for [s %] (f s))) bd)))
>>
>> I don't quite understand the use of `dosync' in the second `board-map'
>> form.  In
>> my testing, the following three seems identical:
>>
>>  (board-map #(dosync (deref %) board)
>>  (dosync (board-map deref board))  ;; Should be the same as above
>>  (board-map deref board)  ;; Without `dosync' at all
>>
>> The docstring of `deref' says "Within a transaction, returns the in-
>> transaction-value
>> of ref, else returns the most-recently-committed value of ref."  So
>> the above three
>> forms are all the same, right?  Or is there any difference between
>> them?
>>
>> Thanks in advance,
>> Guanpeng Xu
>
>
>

-- 
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