Clojure Leiningen、repl、uberjar:无法解析符号,没有这样的变量

Clojure Leiningen、repl、uberjar:无法解析符号,没有这样的变量,clojure,leiningen,read-eval-print-loop,uberjar,Clojure,Leiningen,Read Eval Print Loop,Uberjar,虽然我的lein新应用程序项目在Light Table中愉快地运行,lein uberjar无法工作。奇怪的是,它的行为与经典的Pascal编译器完全相同:它不能在定义之前解析引用。另一个好奇:昨天它成功了。我不知道拿什么敏感的东西开玩笑 谷歌表示,sub症状相当普遍;我尝试过任何能帮助其他处于同样困境的人的方法,但都没有用。顺便说一句,他们通常将其归咎于软件缺陷:“获取最新版本的Leiningen和Clojure”。我有2.5.0和1.6 项目(主文件)位于以下位置: 实际上,解析的参数不能在

虽然我的lein新应用程序项目在Light Table中愉快地运行,lein uberjar无法工作。奇怪的是,它的行为与经典的Pascal编译器完全相同:它不能在定义之前解析引用。另一个好奇:昨天它成功了。我不知道拿什么敏感的东西开玩笑

谷歌表示,sub症状相当普遍;我尝试过任何能帮助其他处于同样困境的人的方法,但都没有用。顺便说一句,他们通常将其归咎于软件缺陷:“获取最新版本的Leiningen和Clojure”。我有2.5.0和1.6

项目(主文件)位于以下位置: 实际上,解析的参数不能在构建相册中解析;如果我将-main函数移到文件的顶部,cli选项inside-main中不会出现这样的变量。不管怎么摆弄名称空间的显式使用都不会有任何区别


同样,在Light表中,一切运行正常。

在函数中使用
def
不是惯用方法,尤其是在没有理由将其作为全局变量的情况下。只需将其作为函数参数传递:

(let [parsed-args (parse-opts ...)]
  ...
  (build-album parsed-args))
如果您确实需要全局状态,您可以使用例如承诺(或者原子):

但是,Clojure文件是从上到下读取的,是的,没有访问文件后面介绍的绑定的函数是设计的。您可以使用
declare
告诉解析器预期的内容:

(declare ^:dynamic *parsed-args*)
(defn build-album ...)
(def ^:dynamic *parsed-args* ...)
...
(binding [*parsed-args* (parse-opts ...)]
  (build-album))
TL;DR:如果没有必要,避免全局状态;如有必要,将其最小化。

非常感谢您,xsc!不知何故,我无法让自己相信,声明可能以这样一种经过彻底解释的语言存在。尽管显而易见。
(declare ^:dynamic *parsed-args*)
(defn build-album ...)
(def ^:dynamic *parsed-args* ...)
...
(binding [*parsed-args* (parse-opts ...)]
  (build-album))