我想在Java中使用Clojure代码。 Clojure代码本身应该实现Java接口(TestGenClassInterface
)。
我的project.clj是:
(defproject com.stackoverflow.clojure/tests "0.1.0-SNAPSHOT"
:description "Tests of Clojure test-framework."
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.6.0"]
[instaparse "1.3.4"]]
:source-paths ["src/main/clojure"]
:java-source-paths ["src/main/java"]
:test-paths ["src/test/clojure"]
:java-test-paths ["src/test/java"]
;:aot :all
)
Java界面如下所示:
package com.stackoverflow.clojure;
public interface TestGenClassInterface {
public String addToString(String text, String appendText);
}
Clojure代码是:
(ns com.stackoverflow.clojure.testGenClass
(:gen-class
:name com.stackoverflow.clojure.TestGenClass
:implements com.stackoverflow.clojure.TestGenClassInterface
:prefix "java-"))
(def ^:private pre "START: ")
(defn java-addToString [this text post]
(str pre text post))
(java-addToString "TexT" " :END")
我预计,在运行lein compile
或"运行为Clojure-Application"在eclipse + CounterClockwise中生成一个.class文件(名为TestGenClass.class
)并保存在*compile-path*
内(此处:target / classes / com / stackoverflow / clojure /)。不幸的是,它不是。
将:aot :all
添加到我的project.clj时,我得到以下stacktrace:
Compiling com.stackoverflow.clojure.testGenClass
Exception in thread "main" java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(com/stackoverflow/clojure/testGenClass.clj:1:1)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6651)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782)
at clojure.lang.Compiler$TryExpr$Parser.parse(Compiler.java:2191)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6644)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5217)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3846)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6642)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6632)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3665)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
at clojure.lang.Compiler.analyze(Compiler.java:6445)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler.compile1(Compiler.java:7221)
at clojure.lang.Compiler.compile1(Compiler.java:7216)
at clojure.lang.Compiler.compile(Compiler.java:7292)
at clojure.lang.RT.compile(RT.java:398)
at clojure.lang.RT.load(RT.java:438)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5066.invoke(core.clj:5641)
at clojure.core$load.doInvoke(core.clj:5640)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5446)
at clojure.core$compile$fn__5071.invoke(core.clj:5652)
at clojure.core$compile.invoke(core.clj:5651)
at user$eval9.invoke(form-init4595004281107083893.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6703)
at clojure.lang.Compiler.eval(Compiler.java:6693)
at clojure.lang.Compiler.load(Compiler.java:7130)
at clojure.lang.Compiler.loadFile(Compiler.java:7086)
at clojure.main$load_script.invoke(main.clj:274)
at clojure.main$init_opt.invoke(main.clj:279)
at clojure.main$initialize.invoke(main.clj:307)
at clojure.main$null_opt.invoke(main.clj:342)
at clojure.main$main.doInvoke(main.clj:420)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
at clojure.lang.RT.seqFrom(RT.java:505)
at clojure.lang.RT.seq(RT.java:486)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$map$fn__4245.invoke(core.clj:2551)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:484)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$map$fn__4245.invoke(core.clj:2551)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.boundedLength(RT.java:1654)
at clojure.lang.RestFn.applyTo(RestFn.java:130)
at clojure.core$apply.invoke(core.clj:624)
at clojure.core$mapcat.doInvoke(core.clj:2586)
at clojure.lang.RestFn.invoke(RestFn.java:423)
at clojure.core$generate_class.invoke(genclass.clj:164)
at clojure.core$gen_class.doInvoke(genclass.clj:638)
at clojure.lang.RestFn.invoke(RestFn.java:1557)
at clojure.lang.Var.invoke(Var.java:519)
at clojure.lang.AFn.applyToHelper(AFn.java:270)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.lang.Compiler.macroexpand1(Compiler.java:6552)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6630)
... 46 more
Compilation failed: Subprocess failed
答案 0 :(得分:1)
根据http://clojure.org/compilation
...实例方法的实现函数总是需要一个 另外的第一个arg对应于调用该方法的对象 在这里,通过惯例称为“这个”。
尝试将“this”添加到每个函数定义中。
(defn java-addToString [this text post]
...
答案 1 :(得分:1)
您遇到的最近问题是:aot :all
文件中缺少project.clj
。如果没有这个,就不会尝试提前编译。
一旦你把它放进去,你将会遇到以下进一步的问题:
您必须在指定为Java方法的函数名称前加上前缀(默认前缀为-
);
您必须包含this
作为每个此类方法的显式第一个参数(this
是推荐的约定,但任何名称都是可接受的);
您必须更正:implements
子句:它需要向量作为值,即使它只有一个成员。
答案 2 :(得分:0)
http://clojure.org/compilation提到编译过程使用
... * compile-path *,必须在类路径中
默认位置是classes文件夹。
Stack Overflow问题Compiling Clojure?的第二个答案提到此路径是相对于jvm启动文件夹的。如果你从主项目文件夹(project.clj所在的文件夹)中进行了lein repl,那么创建一个classes文件夹应该可以使它工作。