Search code examples
clojurelazy-sequencesuberjar

How to force evaluation of lazy seqs in Clojure when running from an uberjar?


Consider the following MWE:

(ns toto.core
(:gen-class))

(defn write-something [i]
  (spit (str "out-" (str i) ".txt") "Hi there!"))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (dorun (pmap write-something (range 16))))

If I run -main from the REPL, it works as expected: it creates the files and returns. However, if I create an uberjar and run java -jar <toto.whatever-standalone.jar> it will create the files, but fail to exit the program. I suspect it is an issue with laziness, but can't figure why the dorun is not working as I'd expect. Any ideas on what I'm doing wrong?


Solution

  • In Clojure the pmap function uses future calls that utilize a common thread pool. The threads in the pool stay alive for a 1 minute after they have finished their tasks in order to reduce the cost of thread allocation.

    If you are sure that the thread pool can be shut down (because the application quits) you need to call shutdown-agents after the (dorun ...) so the thread pool is killed.

    Alternatively, you can call (System/exit <status>) to shut down the application instantly.