我发现在编写代码时添加了警告,这些代码编写了一个文件正文在编译期间执行两次的宏 . 是否有一个原因?这是leiningen特有的吗?我不能用 (compile ...)
重现这个 .
简化版:
(ns foo.core
(:require foo.bar))
;; empty
(ns foo.bar)
(println "hello")
$ lein compile:all编译foo.core你好编译foo.bar你好
进一步测试表明在编译期间命名空间在其自身上重新加载:
(ns foo.bar)
(declare wasd)
(println wasd)
(def wasd 2)
$ lein clean $ lein compile:all编译foo.core#<Unbound Unbound:#'foo.bar / wasd>编译foo.bar 2
在一个更复杂的情况下,我在编译期间发生这种情况,然后每次运行或从lein开始一次repl . 我不知道为什么 . 这完全是clojure 1.6和leiningen 2.5.0 .
2 回答
Leiningen在名称空间如何与彼此相关方面对项目的结构一无所知 . 因此,在编译项目时,
lein
只是引导JVM并强制每个名称空间一次加载一个 . 这意味着,正如您所注意到的,将重新加载名称空间,从而导致您注意到的双重评估行为 .相比之下,(clojure.core/compile)只是使用clojure.core/compile-files bound加载目标资源 . 这将导致目标资源及其所需的所有资源被加载并编译为类文件 . 但是,它不会遍历整个项目结构,因为Leiningen的编译操作会编译所有资源 .
您在编译期间看到
println
输出的原因是因为在命名空间评估期间调用println
. 你的程序应该有-main
fn或其他一些调用println
的入口点 .我认为您的项目正在抛出一个未绑定的异常,因为您在为其分配值之前尝试使用
println
引用wasd
变量 . 声明了变量,但在println
fn尝试获取值之前没有为其分配任何内容 .