用Java直接调用`clojure.lang.Compiler.compile`来AOT编译Clojure

5
使用clojure.lang.Compiler.compile从Java编译Clojure是否合法?
我们的Java应用程序以前使用clojure.lang.Compiler.load在.clj源文件上创建Clojure对象实例,该文件具有proxy宏。现在我们想使用gen-class而不是proxy来AOT编译这些对象。这样,.class文件可以移动并稍后实例化对象。
到目前为止,我做到的最好的事情是说服clojure.lang.Compiler.compile为我生成加载器类文件(“my/domain/lib__init.class”)。但是,我似乎没有得到相应的.class文件,每个函数在命名空间中一个(“my/domain/lib$fnname__1234.class”),以及每个gen-class的存根类文件。这是在沙箱中使用第一个非常简单的示例进行的http://clojure.org/compilation。我认为我已经正确设置了compile-path,并将其设置为类路径中的某个内容,但也许还存在问题。
无论如何,我们实际的应用程序是基于RCP(Eclipse)的,这可能意味着在OSGI类加载器类路径方面还有更多要解决的问题。同时,我只是想知道直接使用clojure.lang.Compiler.compile是否有效?
编辑:所以现在我已经让它生成所有的.class文件,但它需要各种未记录的初始化方法,这表明我认为clojure.lang.Compiler上的方法是内部方法。我必须适当地设置*compile-path*和*compile-files*为true,例如:
RT.var("clojure.core", "*compile-files*").bindRoot(true);
2个回答

2

1
我相信Ankur的建议是直接从Java中调用clojure.core/compileRT.var("clojure.core", "compile").invoke(...)。从Java中获取变量并执行它们比尝试使用clojure的Java内部机制要少出错,也更不容易混淆。如果我没记错的话,这就是Datomic Java API的实现方式。 - Dave Ray
@DaveRay:是的,这就是我所说的从Java中调用它的意思。 - Ankur

1
这是一个直接从Java驱动Clojure编译器的示例。
        String clojureScript = "(ns user) (def hello (fn [] \"Hello world\"))";
        String notionalScriptFileName="hello.clj";
        String outputDirectory="/my/output/dir";

        Var compilePath = RT.var("clojure.core", "*compile-path*");            
        Var compileFiles = RT.var("clojure.core", "*compile-files*");

        Var.pushThreadBindings(RT.map(compilePath, outputDirectory, compileFiles, Boolean.TRUE));                        
        Compiler.compile(new StringReader(clojureScript), notionalScriptFileName, notionalScriptFileName);
        Var.popThreadBindings();

我已经使用Clojure 1.4.0进行了测试...其他版本可能会有所不同。
目前的API需要提供一个“名义”文件名。这似乎只用于生成.class文件名。它生成的类文件将被写入outputDirectory。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接