【问题标题】:How to require namespace inside function -main?如何在函数-main中要求命名空间?
【发布时间】:2014-10-14 17:01:48
【问题描述】:

假设在 Leiningen 项目中哟,我有这些文件:

foo.clj:

(ns yo.foo)
(def x 234.5)

bar.clj:

(ns yo.bar)
(def x -15)

我有一个主文件(core.clj):

(ns yo.core)
(require '[yo.foo :as f])
(when (= f/x 234.5) (println "Succesfully required foo."))
(defn -main [& args]
  (println (require '[yo.bar :as b]))
  ;(when (= b/x -15) (println "Succesfully required bar."))
 )

当我在命令行输入“lein run”时,我得到这个输出:

Succesfully required foo.
nil

第一行告诉我,我了解如何在文件的顶层使用require 函数。 (通常我会在ns 语句中使用:require。)第二行似乎表明我成功地需要yo.bar

但是,当我在 -main 中取消注释包含 when 的行时,出现异常: java.lang.RuntimeException: No such namespace: b, compiling:(yo/core.clj:6:9).

有没有办法从函数内部执行请求?我的目标是在命令行上传递命名空间的名称,然后加载该命名空间。还有另一种方法可以做到这一点吗? (我已经知道如何从-main 中访问命令行参数。)

(问题不在于我用println 包装了require 调用。如果-main 的第一行只显示(require '[yo.bar :as b]),我会得到同样的异常。)

this question 的标题看起来好像和我的一样,但问题和答案并没有解决在函数内部需要命名空间的问题。)

【问题讨论】:

    标签: clojure namespaces


    【解决方案1】:

    编译期间不调用函数-main 中的require 语句。因此编译器无法解析命名空间b 并报错。

    【讨论】:

    • 我明白了。即require 确实在运行时触发,但到那时为时已晚。谢谢莱昂。这听起来好像没有办法使用在运行时选择的命名空间,除非通过显式调用编译器或在运行时将源代码扔到 repl 中,或者可能使用load-file。但我想可以使用我链接到的问题中描述的方法。这动态地获取命名空间,但来自环境而不是通过解析命令行参数。如果我想在命令行上传递命名空间,我可以从设置环境变量的 shell 脚本中调用 lein
    • 事实证明,我可以将命令行中的代码传递给load-string 并识别新加载的命名空间——这是我最初想做的事情。由于load-string 也会导致在运行时进行编译,因此命名空间也被编译这一事实不是问题。
    • (require ...)是顶级语句,编译时如何调用?
    • @HappyFace 调用所有顶级表单的编译效果
    猜你喜欢
    • 2016-03-20
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多