不能在ns:gen-class中使用来自另一个命名空间的类

时间:2017-08-26 19:53:00

标签: clojure clojure-java-interop

我在defrecord命名空间中有一个名为ConstraintLookup的{​​{1}}。 我想在放置在sre.plan.dsl.constraint命名空间的gen-class方法中使用其生成的类:

sre.plan.compiler

我正在使用(ns sre.plan.compiler (:require [sre.plan.dsl.constraint :as constraint]) (:import (sre.plan.dsl.constraint ConstraintLookup)) (:gen-class :name sre.plan.Compiler :methods [^:static [makeConstraintLookupFromTargetsAndBounds [Iterable Iterable] ConstraintLookup]])) 插件和Gradle进行AOT编译。编译器在遇到ns声明时会发出错误:

nebula-clojure

同样,在方法声明中使用完全限定的> Task :sre:compileClojure Exception in thread "main" java.lang.ClassNotFoundException: java.lang.ConstraintLookup, compiling:(sre/plan/compiler.clj:1:1) 时,我得到:

sre.plan.dsl.constraint.Constraint

这是什么问题?我迷路了。

更新:

引用的ns如下所示:

Exception in thread "main" java.lang.ClassNotFoundException: sre.plan.dsl.constraint.ConstraintLookup, compiling:(sre/plan/compiler.clj:1:1)

更新:

在我看来,无论如何,在gen-class中你必须使用完全限定的类名。但是,我仍然不明白为什么没有完全限定名称的版本。

1 个答案:

答案 0 :(得分:2)

:gen-class宏内的ns指令很可能无法引用同一形式的:require副作用生成的类。在调用任何ns之前,gen-class宏发出的代码会调用require。因此,在调用gen-class时,尚未编译所需的命名空间。在生成gen-class的任何类之前调用​​defrecord

ns的行为in the source code以及使用macroexpand的repl中的行为:

(clojure.pprint/pprint (macroexpand '(ns sre.plan.compiler
  (:require
    [sre.plan.dsl.constraint :as constraint])
  (:import (sre.plan.dsl.constraint ConstraintLookup))
  (:gen-class
    :name sre.plan.Compiler
    :methods [^:static [makeConstraintLookupFromTargetsAndBounds 
                         [Iterable Iterable] ConstraintLookup]]))))
;; (do
;;  (clojure.core/in-ns 'sre.plan.compiler)
;;  (clojure.core/with-loading-context
;;    (clojure.core/gen-class
;;     :name
;;     "sre.plan.compiler"
;;     :impl-ns
;;     sre.plan.compiler
;;     :main
;;     true
;;     :name
;;     sre.plan.Compiler
;;     :methods
;;     [[makeConstraintLookupFromTargetsAndBounds
;;       [Iterable Iterable]
;;       ConstraintLookup]])
;;    (clojure.core/refer 'clojure.core)
;;    (clojure.core/require '[sre.plan.dsl.constraint :as constraint])
;;    (clojure.core/import '(sre.plan.dsl.constraint ConstraintLookup)))
;;   (if
;;    (.equals 'sre.plan.compiler 'clojure.core)
;;    nil
;;    (do
;;     (clojure.core/dosync
;;      (clojure.core/commute
;;       @#'clojure.core/*loaded-libs*
;;       clojure.core/conj
;;       'sre.plan.compiler))
;;     nil)))

要解决此问题,我们可以在gen-class之后致电ns。例如:

(ns sre.plan.compiler
  (:require
    [sre.plan.dsl.constraint :as constraint])
  (:import (sre.plan.dsl.constraint ConstraintLookup)))

(gen-class
 :impl-ns
 sre.plan.compiler
 :main
 true
 :name
 sre.plan.Compiler
 :methods
 [[makeConstraintLookupFromTargetsAndBounds
   [Iterable Iterable]
   sre.plan.dsl.constraint.ConstraintLookup]])