尝试将内容映射到println时ref为空

时间:2015-12-30 00:01:51

标签: clojure

我不确定自己是否遇到某种竞争条件,但是我正在将一些测试代码放在一起测试在Clojure中使用传统的面向对象的范例,我碰到了一些有趣的行为。检查以下代码:

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

当我在REPL中运行代码时,一切正常:print-registrar成功将记录从注册商传递到print-record,并按预期打印,如下:

Registrar's Report
------------------
Rick James
Charlie Murphy
(nil nil)

但是当我尝试从命令行运行代码时,我得到以下内容:

Registrar's Report
------------------

这是因为dosync是异步调用还是其他什么?当我在致电map之前转储注册商的内容时,我会看到我对它的期望,所以我有点困惑。

1 个答案:

答案 0 :(得分:2)

map与副作用混合起来通常不是一个好主意,因为map是懒惰的,因此副作用不会发生,除非有些东西穿过序列并且强制副作用(在这种情况下,repl会为你做这件事)。

我认为run!应该是替代品,因为print-record不会返回任何有用的内容。