Gen-Class не создает файл.class

Я хотел бы использовать код Clojure в Java. Сам код Clojure должен реализовывать Java-интерфейс (TestGenClassInterface).

Мой project.clj это:

(defproject com.stackru.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.stackru.clojure;

public interface TestGenClassInterface {

    public String addToString(String text, String appendText);

}

Код Clojure:

(ns com.stackru.clojure.testGenClass
  (:gen-class
     :name com.stackru.clojure.TestGenClass
     :implements com.stackru.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/stackru/clojure/). К сожалению это не так.

При добавлении :aot :all в мой project.clj я получаю следующую трассировку стека:

Compiling com.stackru.clojure.testGenClass
Exception in thread "main" java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(com/stackru/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

3 ответа

Решение

Ближайшая проблема, которую вы имеете, - это отсутствие :aot :all в вашем project.clj файл. Без этого преждевременная компиляция не будет предпринята.

После этого у вас появятся следующие дополнительные проблемы:

  • Вы должны поставить префикс имен функций, предназначенных для превращения в методы Java (префикс по умолчанию -);

  • Вы должны включить this в качестве явного первого аргумента каждого такого метода (this является рекомендуемым соглашением, но допустимо любое имя);

  • Вы должны исправить свои :implements предложение: он принимает вектор в качестве значения, даже если он имеет один член.

Согласно http://clojure.org/compilation

... функции реализации для методов экземпляра всегда будут принимать дополнительный первый аргумент, соответствующий объекту, к которому вызывается метод, который вызывается здесь соглашением 'this'.

Попробуйте добавить "это" к каждому определению функции.

(defn java-addToString [this text post]
  ...

http://clojure.org/compilation упоминает, что процесс компиляции использует

... * путь компиляции *, который должен находиться в пути к классам

Расположение по умолчанию - папка классов.

Второй ответ на вопрос переполнения стека Компилирование Clojure? упоминает, что этот путь относительно папки запуска jvm. Если вы выполнили lein repl из основной папки проекта (папки, в которой находится project.clj), то создание папки классов должно заставить ее работать.

Другие вопросы по тегам