【问题标题】:Leiningen, repl, uberjar: Unable to resolve symbol, No such varLeiningen、repl、uberjar:无法解析符号,没有这样的 var
【发布时间】:2015-01-13 02:16:30
【问题描述】:

虽然我的 lein new app 项目在 Light Table 中愉快地运行,但 lein uberjar 将无法工作。奇怪的是,它的行为与经典的 Pascal 编译器完全一样:它无法在定义之前解析引用。另一个好奇心:昨天它起作用了。我不知道有什么敏感的东西在愚弄。

Google 说,主题症状很常见;我尝试了任何可以帮助处于相同(?)困境中的其他人的方法,但无济于事。顺便说一句,他们通常将其归咎于软件错误:“获取最新版本的 Leiningen 和 Clojure”。我有 2.5.0 和 1.6。

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

同样,在 Light Table 内一切正常。

【问题讨论】:

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


    【解决方案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:如果没有必要,避免全局状态;如有必要,将其最小化。

    【讨论】:

    • 非常感谢,xsc!不知何故,我无法让自己相信声明可能以如此彻底的解释语言存在。尽管显而易见。
    猜你喜欢
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 2015-12-09
    • 2011-10-10
    • 2021-12-14
    • 2014-10-01
    • 2018-11-11
    • 2015-11-25
    相关资源
    最近更新 更多