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

欢迎!请查看关于 页面以了解更多关于如何工作的信息。

+1
Clojure
(ns graalvm-list-issue.main
  (:require
   [clojure.java.io :as io])
  (:gen-class))

(defn- home-path []
  (System/getProperty "user.home"))

(defn- local-dir []
  (io/file (home-path) ".local"))

(defn -main [& _args]
  (println (seq (.list (io/file (home-path) ".local"))))
  (println (seq (.list (local-dir)))))

(完整代码在此: https://github.com/conao3/clojure-graalvm-list-issue)

第一条 println 行没有反射,第二条 println 行有反射,并且在 GraalVM 中执行时发生错误。
我看不出这两个调用之间的区别,并且由于显然 local-dir 的返回值是 io/file,因此它应该推断为 java.io.File。您怎么看?


调查 Clojure 源代码

关键函数是 hasJavaClassgetJavaClass
https://github.com/clojure/clojure/blob/8c8e4f6ef21f3d0f59deb60cdc7e1b584f596d59/src/jvm/clojure/lang/Compiler.java#L359-L361

FnExpr: https://github.com/clojure/clojure/blob/8c8e4f6ef21f3d0f59deb60cdc7e1b584f596d59/src/jvm/clojure/lang/Compiler.java#L4450-L4454

InvokeExpr: https://github.com/clojure/clojure/blob/8c8e4f6ef21f3d0f59deb60cdc7e1b584f596d59/src/jvm/clojure/lang/Compiler.java#L4286-L4290

2 个答案

0

local-dir 实际上返回 Object,因为在 Clojure 中所有函数在没有返回类型提示的情况下都这样做。这里没有推断。

您可以将它提示为返回 File(defn- local-dir ^java.io.File [] ..)

然后您就不会遇到反射问题了。

by
分析代码,很明显`io/file`的返回值是函数的返回值,由于`io/file`的返回值是`java.io.File`,因此我们可以推测函数本身的返回值也是`java.io.File`。
0
by

虽然在这个例子中这似乎很明显,但是一旦你引入了条件语句/多个尾随位置以及原语,它就会变得相当复杂。在具有多个尾随位置的情况下,答案可能是多个答案——在这种情况下,你可能需要找到公共的超类型或者忽略。

此外,由于类型提示主要用于Java互操作,实际上需要返回类型提示的情况相对较少(许多程序可能没有这种情况)。

截至目前,投入有限的使用价值的努力可能不值得,但将来可能需要考虑。

...