Reputation: 1780
I'm not sure if I'm running into some sort of race condition, but I was throwing together some test code to test working in a traditional object-oriented paradigm in Clojure, and I ran into some funny behavior. Examine the following code:
(def registrar (ref #{}))
(defrecord Person [first-name last-name])
(def rick (->Person "Rick" "James"))
(def charlie (->Person "Charlie" "Murphy"))
(dosync
(alter registrar conj rick)
(alter registrar conj charlie))
(defn print-record
[record]
(println (format "%s %s", (:first-name record), (:last-name record))))
(defn print-registrar
"Prints a report of the registrar to stdout"
[registrar]
(println "Registrar's Report\n------------------")
(map print-record registrar))
(let [registrar (deref registrar)]
(print-registrar registrar))
When I run the code in my REPL, all is well: print-registrar
successfully passes records from the registrar to print-record
and they are printed as expected, as such:
Registrar's Report
------------------
Rick James
Charlie Murphy
(nil nil)
But when I try to run the code from the command line, I get the following:
Registrar's Report
------------------
Is this because dosync
is called asynchronously or something? When I dump the contents of the registrar before calling map
, I see what I expect in it, so I'm slightly confused.
Upvotes: 0
Views: 34
Reputation: 1322
Mixing map
with side-effects isn't usually a good idea, since map
is lazy, and therefore the side effects won't happen unless something walks through the sequence and forces the side effects (in this case, the repl does it for you).
I think run!
should be a drop-in replacement here, since print-record
doesn't return anything useful.
Upvotes: 2