Clojure 为什么'lein uberjar'计算用'def'定义的变量?
我试图理解创建Clojure 为什么'lein uberjar'计算用'def'定义的变量?,clojure,leiningen,Clojure,Leiningen,我试图理解创建uberjar时的“Lieningen”行为。以下是再现该行为的最小示例: (ns my-stuff.core (:gen-class)) (def some-var (throw (Exception. "boom!"))) (defn -main [& args] (println some-var)) 当使用lein run执行此操作时显然会出现异常。然而,我不明白为什么执行leinuberjar也会失败,因为变量定义中有一个异常?为什么执行leinub
uberjar
时的“Lieningen”行为。以下是再现该行为的最小示例:
(ns my-stuff.core
(:gen-class))
(def some-var (throw (Exception. "boom!")))
(defn -main [& args]
(println some-var))
当使用
lein run执行此操作时
显然会出现异常。然而,我不明白为什么执行leinuberjar
也会失败,因为变量定义中有一个异常?为什么执行leinuberjar
会尝试计算变量值?这是针对uberjar
任务的,还是我遗漏了Clojure或Leiningen更重要的内容?为了为uberjar编译名称空间(如果您已启用AOT),Clojure编译器必须加载您的名称空间。这将始终调用所有顶级副作用
处理这一问题的最佳方法是,在顶级代码中(无论是在def
表单内部还是外部)永远不要有副作用,并具有初始化功能以实现所需的任何启动副作用
一种解决方法是创建一个小型命名空间,在运行时使用内省加载其余代码,但在编译时不加载—使用如下函数:
(defn -main
[]
(require 'my.primary.ns)
((resolve 'my.primary.ns/start)))
如果编译了该名称空间,jvm可以找到-main并运行它,尽管没有编译任何其他代码。运行时require
将导致Clojure编译器仅在运行时加载其余代码,并且需要resolve
,以便-main
将干净地编译-它返回引用的变量,然后在调用函数时调用您的函数