Почему lein run зависает?

Я создал проект Leiningen для упражнения 2 из здесь. Мой код выглядит так:

(ns random-quotes.core
  (:require [clojure.string :as str])
  (:gen-class))

(defn word-count [s]
  (frequencies (str/split (first (str/split s #"\n")) #"\s")))

(def quote-url "http://www.braveclojure.com/random-quote")

(def total-word-count (atom {}))

(defn update-word-count []
  (future
    (swap! total-word-count
           (partial merge-with +)
           (word-count (slurp quote-url)))))

(defn quote-word-count [n]
  (doseq [quote-future (doall (repeatedly n update-word-count))]
    @quote-future)
  @total-word-count)

(defn -main [n]
  (doseq [entry (sort-by val (quote-word-count (bigdec n)))]
    (println entry)))

Все довольно просто. Когда я запускаю, например, (-main 5) в lein repl, он запускается, печатает и возвращает результат, как и ожидалось. Однако, когда я вместо этого пытаюсь использовать lein run 5, он запускается и печатает, но никогда не завершает работу, поэтому я вынужден использовать Ctrl+C, чтобы вернуть свой терминал.

Любая идея, почему это происходит?


person Sam Estep    schedule 26.10.2015    source источник


Ответы (1)


Clojure имеет пул потоков, который он поддерживает для использования агентами. Поскольку эти потоки все еще живы, JVM не может сказать, что ваша программа выполнена. Он просто сидит и ждет выхода агентов. Вы можете завершить их, вызвав (shutdown-agents) в конце своей программы, как описано здесь. Фьючерсы используют агентов.

clojure.core/future-call вызывает агента следующим образом:

(let [f (binding-conveyor-fn f)
      fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)]

который фактически запускает ваш код. Вы не единственный, кто высказал некоторую критику этого, и мы все надеемся, что будет найдено более элегантное решение.

person Arthur Ulfeldt    schedule 26.10.2015
comment
@Elogent - вы вызывали агентов, когда использовали future. - person DaoWen; 27.10.2015
comment
спасибо @Elogent, я отредактирую, чтобы включить это в ответ. - person Arthur Ulfeldt; 27.10.2015