次のコードでは、チャネルをリッスンし、読み取った値をエージェントに書き込む go ループを使用しています。次に、同じループで、log-to-file 関数がエージェントの各項目をファイルに書き込むことになっています。ただし、[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
...