在下面的代码中,我使用了一个 go 循环,它在通道上侦听并将它读取的值写入代理。然后,在同一个循环中,日志到文件功能应该将代理上的每个项目写入文件。但是,文件的输出是不寻常的,因为具有 [8 6 5 13] 的代理可能会将其内容作为 865n13 吐到文件中。如果我从记录器函数中删除日志到文件调用并单独调用它,有时文件输出很好,有时不是。有人可以向我解释发生了什么,并可能向我展示一种安全的方法来证明一致的行为吗?我知道不使用代理可能是实现一致行为的最佳方式。我只是想知道,本着学习的精神,使用代理可以实现什么,不可以实现什么。提前感谢!
(defn log-to-file [file] (for [i (deref log)] (spit file (str "\n" i) :append true)))
(defn logger [file]
(go
(loop []
(when-let [v (<! print-chan)]
(send log conj v)
(log-to-file file)
(recur)))))
;; testing it out
(def log (agent []))
(>!! print-chan 5)
(logger "resources/test.txt")
(deref log)
编辑:
这是根据下面接受的答案中的评论重写的代码。我完全不建议使用此代码,或者就此而言,在 go 循环中使用具有副作用的代理。
(def ch (chan))
(def a (agent []))
(defn double-async-print []
(go-loop []
(when-let [x (<! ch)]
(send a conj x)
(print (clojure.string/join "\n" @a)))
(recur)))
(go (doseq [n (range 10)] (>! ch n)))
(double-async-print)
;=>jsync 0.1.0-SNAPSHOT[stdout]:
00
10
1
20
1
2
30
1
2
3
40
1
...