请在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)它
    不返回一个集合或数组。

2 个答案

0

除了我之外,其他人可以在这里给出更权威的答案,但我就个人而言,我确信Clojure编译器为Clojure函数和deftype方法创建的方法可以有三种类型:java.lang.Object、原始的长整型(long)或原始的双精度浮点型(double)作为参数类型和返回类型。除此之外,最有效的方法是使用除了Clojure编译器之外的其他工具来创建JVM的字节码,例如编写一些Java包装代码并用javac编译,或者学习一些生成JVM字节码的库,比如Clojure库使用的asm库。

这是正确的。如果你想要一个特定类型的类,你可以创建一个接口,这个接口具有特定的类型,然后让deftype实现这个接口。
这里的问题是optaplanner强制执行大量的注解,并且在验证阶段特别反映在类上注解字段。如果字段未类型化(deftype强制为object),则optaplanner会崩溃。即使提供了一个具有getters和setters的接口。反射发生在字段上。尽管有其他解决方案,但似乎完全符合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}}}}
...