我发现在向编写宏的过程中添加警告时,文件正文在编译过程中被执行了两次。是否有一个原因?这是leiningen特有的吗?我无法使用(compile ...)
重现此内容。
简化版:
(ns foo.core
(:require foo.bar))
;; empty
(ns foo.bar)
(println "hello")
$ lein compile:all
编译foo.core
hello
编译foo.bar
hello
进一步的测试表明,在编译期间,命名空间会自行重新加载:
(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。
答案 0 :(得分:5)
Leiningen在名称空间如何与彼此相关方面对项目的结构一无所知。因此,在编译项目时,lein
只是引导JVM并强制每个名称空间一次加载一个。这意味着,正如您所注意到的,名称空间将被重新加载,从而导致您注意到的双重评估行为。
相比之下,(clojure.core/compile)
只会加载clojure.core/*compile-files*
绑定的目标资源。这将导致目标资源及其所需的所有资源被加载并编译为类文件。但是,它将不遍历整个项目结构,编译所有资源,如Leiningen的编译操作。
答案 1 :(得分:1)
您在编译期间看到println
输出的原因是因为在命名空间评估期间调用了println
。您应该有一个-main
fn或其他一些可以调用println
的程序的入口点。
(defn -main [& _]
(println "Won't see on compile.")
(println "lein run -- is printing from -main"))
我认为您的项目正在抛出一个未绑定的异常,因为您在为其分配值之前尝试使用wasd
引用println
变量。声明了变量,但在println
fn尝试获取值之前没有为其分配任何内容。