请在2024 Clojure状态调查!中分享您的想法。

欢迎!请访问关于页面以获取有关此页面如何工作的更多信息。

0票数
Java互操作性
  (deftype l [^java.util.List x])
  (use '[clojure.reflect :as r])
  (:members (r/reflect (l. `())))

尽管有java.util.List的类型提示,但在反射中x似乎始终是Object类型

我正在尝试在100% Clojure中运行optaplanner示例https://github.com/joinr/optaplanner-clj/tree/163d326a6433b88ca9811e33d30758ceff42b91f。代码已评估,但在运行(solve (->problem))时持续出现此错误。

  1. 未处理的java.lang.IllegalStateException:solutionClass(class optaplanner_clj.data.TimeTable)有一个
    PlanningEntityCollectionProperty标注的成员
    public final java.lang.Object optaplanner_clj.data.TimeTable.lessonList
    没有返回Collection或数组

2个答案

0票数

除了我之外,还有其他人可以更权威地回答这里,但我想 Clojure编译器为Clojure函数和deftype方法创建的方法,参数类型和返回类型可以是java.lang.Object、原始long或原始double之一。对于其他任何类型,您最有效的方法是使用除Clojure编译器之外的其他方法创建JVM字节码,例如编写一些Java包装代码并用javac编译,或者学习一些用于生成JVM字节码的库,例如Clojure库使用的asm库。

这是正确的。如果你想要一个具有特定类型的类,你可以通过创建一个具有特定类型的接口来实现,然后让deftype实现该接口。
这里的问题是optaplanner强制执行很多注解,并且在验证阶段特别关注类上注解的字段。如果字段没有类型(deftype强制设为对象),那么optaplanner会崩溃。即使提供了带getter和setter的接口。反射发生在字段上。我们还让其他注释垃圾工作。除了其他的一些变通方法,看起来完全符合optaplanner互操作性需要自定义类定义(例如使用insn库),或者处理deftype输出的内容。
0票数

仅供参考,看起来clojure.tools.emitter.jvm确实保留了非原始字段的类型...

 (require '[clojure.tools.emitter.jvm :as e])

(e/eval '(deftype blah [^String x]) {:debug? true})
;;;
// class version 50.0 (50)
// access flags 0x31
public final class user/blah implements clojure/lang/IType  {

  // compiled from: user/blah

  // access flags 0x11
  public final Ljava/lang/String; x
...

user> (require '[clojure.reflect :as r])
nil
user> (r/reflect (user.blah. "hello"))
{:bases #{java.lang.Object clojure.lang.IType},
 :flags #{:public :final},
 :members
 #{{:name getBasis,
    :return-type clojure.lang.IPersistentVector,
    :declaring-class user.blah,
    :parameter-types [],
    :exception-types [],
    :flags #{:public :static}}
   {:name user.blah,
    :declaring-class user.blah,
    :parameter-types [java.lang.Object],
    :exception-types [],
    :flags #{:public}}
   {:name x,
    :type java.lang.String,  ;;in clojure
    :declaring-class user.blah,
    :flags #{:public :final}}}}
...