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不同。也就是说,它们设置常见的绑定,如ns,并将当前命名空间设置为一个新的用户命名空间,通常称为user,其在其中包含了clojure.core的引用。这意味着从#3和#6执行的代码将能够设置常见的绑定,而不会干扰clojure.core命名空间。
第2的上下文将取决于REPL本身是如何从Java启动的。在大多数情况下,clojure.main,lein,boot,它将类似于#3和#6。
我认为为Clojure标准化从Java启动Clojure时的执行上下文将是有益的,这样所有的以上机制都会表现相同。这将确保所有代码都将从所有启动机制平等地运行。这不是目前的情况,因为缺失的绑定和当前clojure.core命名空间可能使某些不太可能的场景在#1、#4和#5中失败,但在#3和#6中工作。
为了避免破坏向后兼容性,最好是增强#1、#4和#5,使其也设置常见的绑定,并将当前命名空间更改为一个新的带有clojure.core引用的用户命名空间。
邮件列表上的初步讨论:https://groups.google.com/forum/#!topic/clojure/6CXUNuPIUyQ