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