In the following code, I am using a go loop that listens in on a channel and writes the values it reads to an agent. Then, in the same loop, the log-to-file function is supposed to write each item on the agent to a file. The output to the file is unusual, however, as an agent with [8 6 5 13] might have its contents spit to the file as 865n13. If i remove the log-to-file call from the logger function and call it separately, sometimes the file output is fine sometimes not. Could somebody just explain to me what is going on and possibly show me a safe way to do this that demonstrates consistent behavior? I am aware that not using an agent would probably be the best way to achieve consistent behavior. I just want to know, in the spirit of learning, what is and isn't possible to achieve with agents. Thanks in advace!
(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)
EDIT:
This is the code rewritten in light of the comments in the accepted answer below. I do not recommend using this code at all, or for that matter ever using an agent in a go loop with side-effects.
(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
...