haven't done any Clojure for couple years, so decided to go back and not ignore core.async this time around ) pretty cool stuff, that - but it surprised me almost immediately. Now, I understand that there's inherent indeterminism when multiple threads are involved, but there's something bigger than that at play here.
The source code for my oh-so-simple example, where I am trying to copy lines from STDIN to a file:
(defn append-to-file
"Write a string to the end of a file"
([filename s]
(spit filename (str s "\n")
:append true))
([s]
(append-to-file "/tmp/journal.txt" s)))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Initializing..")
(let [out-chan (a/chan)]
(loop [line (read-line)]
(if (empty? line) :ok
(do
(go (>! out-chan line))
(go (append-to-file (<! out-chan)))
(recur (read-line)))))))
except, of course, this turned out to be not so simple. I think I've narrowed it down to something that's not properly cleaned up. Basically, running the main function produces inconsistent results. Sometimes I run it 4 times, and see 12 lines in the output. But sometimes, 4 run will produce just 10 lines. Or like below, 3 times, 6 lines:
akamac.home ➜ coras git:(master) ✗ make clean
cat /dev/null > /tmp/journal.txt
lein clean
akamac.home ➜ coras git:(master) ✗ make compile
lein uberjar
Compiling coras.core
Created /Users/akarpov/repos/coras/target/uberjar/coras-0.1.0-SNAPSHOT.jar
Created /Users/akarpov/repos/coras/target/uberjar/coras-0.1.0-SNAPSHOT-standalone.jar
akamac.home ➜ coras git:(master) ✗ make run
java -jar target/uberjar/coras-0.1.0-SNAPSHOT-standalone.jar < resources/input.txt
Initializing..
akamac.home ➜ coras git:(master) ✗ make run
java -jar target/uberjar/coras-0.1.0-SNAPSHOT-standalone.jar < resources/input.txt
Initializing..
akamac.home ➜ coras git:(master) ✗ make run
java -jar target/uberjar/coras-0.1.0-SNAPSHOT-standalone.jar < resources/input.txt
Initializing..
akamac.home ➜ coras git:(master) ✗ make check
cat /tmp/journal.txt
line a
line z
line b
line a
line b
line z
(Basically, sometimes a run produced 3 lines, sometimes 0, sometimes 1 or 2). The fact that lines appear in random order doesn't bother me - go blocks do things in a concurrent/threaded manner, and all bets are off. But why they don't do all of work all the time? (Because I am misusing them somehow, but where?) Thanks!