sent1nel
sent1nel

Reputation: 1780

ref empty when attempting to map contents to println

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

Answers (1)

gfredericks
gfredericks

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

Related Questions