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

时间:2014-11-15 21:55:50

标签: clojure leiningen read-eval-print-loop uberjar

当我的 lein new app 项目在Light Table中快速运行时, lein uberjar 无法正常工作。奇怪的是,它的行为与经典的Pascal编译器完全相同:它无法在定义之前解析引用。另一个好奇心:昨天它起作用了。我不知道愚弄任何敏感的东西。

谷歌表示,这些症状很常见;我在同样的(?)困境中尝试过帮助其他人的任何事情,但无济于事。顺便说一句,通常他们会把它归咎于软件错误:"获得最新版本的Leiningen和Clojure"。我有2.5.0和1.6。

项目(主文件)在这里:https://github.com/Tyrn/pcc/blob/master/src/pcc/core.clj 实际上, parsed-args 无法在 build-album 中解析;如果我将-main函数移动到文件的顶部,'没有这样的var'发生在 cli-options 内部-main。显然使用命名空间的任何数量都不会产生任何影响。

同样,在Light Table内部,一切运行良好。

1 个答案:

答案 0 :(得分:1)

在函数内部使用def不是惯用的,特别是如果没有理由将它作为全局变量。只需将其作为函数参数传递:

(let [parsed-args (parse-opts ...)]
  ...
  (build-album parsed-args))

如果你真的需要全局状态,你可以使用例如承诺(或者,原子):

(defonce parsed-args (promise))
...
(deliver parsed-args (parse-opts ...))

但是,Clojure文件是从上到下读取的,是的,无法访问文件后面引入的绑定的函数是设计使然。您可以使用declare告诉解析器期望的内容:

(declare ^:dynamic *parsed-args*)
(defn build-album ...)
(def ^:dynamic *parsed-args* ...)
...
(binding [*parsed-args* (parse-opts ...)]
  (build-album))

TL; DR:如果没有必要,请避免全局状态;如果有必要,尽量减少它。