Why `lein uberjar` evaluates variables defined with `def`?

杀马特。学长 韩版系。学妹 提交于 2019-12-01 15:45:51

问题


I'm trying to understand "Lieningen" behaviour when creating an uberjar. Following is the minimal example which reproduces the behaviour:

(ns my-stuff.core
  (:gen-class))

(def some-var (throw (Exception. "boom!")))

(defn -main [& args]
  (println some-var))

When this is executed with lein run it clearly fails with an Exception. However, I don't understand why executing lein uberjar also fails with an Exception from variable definition? Why executing lein uberjar attempts to evaluate the variable value? Is this speecific to uberjar task or am I missing something more substantial about Clojure or Leiningen?


回答1:


In order to compile your namespace for the uberjar (if you have AOT turned on), the clojure compiler must load your namespace. This will always invoke all top-level side effects.

The best way to handle this is to never have side effects in top level code (whether inside or outside a def form), and have initialization functions to realize any start-up side effects needed.

A workaround can be to make a small namespace that uses introspection to load the rest of your code at runtime but not while compiling - using a function like this:

(defn -main
  []
  (require 'my.primary.ns)
  ((resolve 'my.primary.ns/start)))

if that namespace is compiled, the jvm can find -main and run it, despite none of your other code being compiled. The runtime require will cause the Clojure compiler to load the rest of your code at runtime only, and resolve is needed so that -main will compile cleanly - it returns the var referenced, which then invokes your function when called.



来源:https://stackoverflow.com/questions/32288195/why-lein-uberjar-evaluates-variables-defined-with-def

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!