Clojure始终必须从Java那里接收程序计数器,JVM不能直接加载到Clojure。所以你有几种方式可以做到这一点:
1) 使用 gen-class
2) 从已经启动的REPL
3) 使用 clojure.main
4) 使用Clojure运行时(RT.java)
5) 使用Clojure Java API(https://clojure.github.io/clojure/javadoc/clojure/java/api/Clojure.html)
6) 使用Leiningen和Boot等流行的工具
每次您想从Java运行一些Clojure代码时,您需要通过这些机制之一来执行它,并且您不能在没有先访问Java的情况下运行Clojure代码。
问题是,并非所有机制都将以相同的环境移交执行。
#1、#4和#5都从Clojure运行时执行的环境移交执行。这意味着你在“clojure.core”命名空间内运行的是一个最小的环境。没有设置绑定,并且ns指向“clojure.core”。
#3和#6似乎都移交了类似的执行环境,但其环境与#1、#4和#5不同。也就是说,它们设置了常见的绑定,例如< strong>ns strong>,并将当前命名空间设置为一个新的命名空间,通常称为user,其在其中引用了clojure.core。
#2的环境将取决于REPL本身如何从Java启动。在大多数情况下,clojure.main、lein、boot,将与#3和#6相似。
我认为,当从Java启动Clojure时,使Clojure的标准执行环境得到统一将是一个健康的选择,以便所有上述机制都能表现一致。这样一来,所有代码都将从所有启动机制中平等地运行。目前并非如此,因为缺少绑定和 clojure.core 当前命名空间可能导致在某些罕见场景下#1、#4和#5失败,但在#3和#6中却可以工作。
为了不破坏向后兼容性,最好增强#1、#4和#5,使它们也设置常见的绑定,并将当前命名空间更改为一个全新的user命名空间,其中包含了对clojure.core的引用。
关于邮件列表的初步讨论: https://groups.google.com/forum/#!topic/clojure/6CXUNuPIUyQ