是否可以键入提示填充了 deftype 对象的 Clojure 数组?

in_*_*ood 3 clojure

我正在优化应用程序的一小部分以性能为重点的部分。我正在尝试创建一个通过以下方式创建的类型的 Java 数组deftype

(deftype MyThing [foo bar baz]) 
Run Code Online (Sandbox Code Playgroud)

但是,我似乎找不到有关如何键入提示这些数组的任何文档,并且如果没有类型提示,就会发生反射。

(def my-array (make-array MyThing 10))
(aget my-array 0)
Run Code Online (Sandbox Code Playgroud)

给出警告:

Reflection warning, call to static method aget on clojure.lang.RT can't be resolved (argument types: core.MyThing, int).
Run Code Online (Sandbox Code Playgroud)

有没有办法正确提示类型?

ama*_*loy 5

我很惊讶在 Stack Overflow 上没有找到关于这个主题的任何问题,更惊讶的是添加类型提示的官方文档没有涵盖这一点 - 我确信我可以将其作为副本关闭,或链接到官方文档,但在这里我像野蛮人一样手工输入。

类型提示的“原始”版本,其他形式只是简写1,是

^"Foo" xs
Run Code Online (Sandbox Code Playgroud)

其中 Foo 是您要提示的类的 JVM 内部名称。有原始数组 ( ^ints xs) 和普通类类型 ( ^MyType x) 的简写,但这不包括非原始类型的数组。为此,您必须知道您的类型的官方类名。您可以查找相关规则,但最简单的方法就是询问口译员!

user=> (defrecord Foo [])
user.Foo
user=> (def foos (make-array Foo 10))
#'user/foos
user=> (class foos)
[Luser.Foo;
user=> (aget foos 0)
Reflection warning, null:1:1 - call to static method aget on clojure.lang.RT can't be resolved (argument types: unknown, int).
nil
user=> (aget ^"[Luser.Foo;" foos 0)
nil
Run Code Online (Sandbox Code Playgroud)

1实际上,更原始的是^{:tag "Foo"},但是这种区别对于这个问题无关紧要。