【问题标题】:Cannot use class from another namespace in ns :gen-class不能在 ns :gen-class 中使用来自另一个命名空间的类
【发布时间】:2018-02-04 13:13:52
【问题描述】:

我在 sre.plan.dsl.constraint 命名空间中有一个名为 ConstraintLookupdefrecord。 我想在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]]))

我正在使用 nebula-clojure 插件和 Gradle 进行 AOT 编译。编译器遇到 ns 声明时会发出错误:

> 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

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

这里有什么问题?我迷路了。

更新:

引用的 ns 如下所示:

(ns sre.plan.dsl.constraint
  (:require [clojure.set :refer :all]
            [clojure.algo.generic.functor :refer :all]))

(defrecord ConstraintLookup [free bound])

更新:

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

【问题讨论】:

  • 您能否创建一个示例项目来重现此错误?

标签: clojure clojure-java-interop


【解决方案1】:

很有可能ns 宏中的:gen-class 指令不能以相同的形式引用作为:require 的副作用而生成的类。 ns 宏发出的代码在调用任何requires 之前调用gen-class。因此,当调用gen-class 时,尚未编译所需的命名空间。在生成来自defrecord 的任何类之前调用​​gen-class

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)))

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

(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]])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-21
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多