я не занимался Clojure пару лет, поэтому решил вернуться и не игнорировать core.async на этот раз) довольно крутая штука, но это меня почти сразу удивило. Теперь я понимаю, что существует неотъемлемая индетерминизм, когда задействовано несколько потоков, но здесь есть нечто большее, чем это.
Исходный код моего очень простого примера, где я пытаюсь скопировать строки из STDIN в файл:
(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)))))))
только, конечно, это оказалось не так просто. Я думаю, что сузил его до чего-то, что не убрано должным образом. По сути, запуск основной функции приводит к противоречивым результатам. Иногда я запускаю его 4 раза и вижу на выходе 12 строк. Но иногда 4 прогона дают всего 10 строк. Или, как показано ниже, 3 раза, 6 строк:
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
(В основном, иногда запуск производил 3 строки, иногда 0, иногда 1 или 2). Тот факт, что строки появляются в случайном порядке, меня не беспокоит — блоки go делают что-то параллельно/поточно, и все ставки сняты. Но почему они не выполняют всю работу все время? (Потому что я как-то злоупотребляю ими, но где?) Спасибо!