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 [] ..)

这样就不会有反射。

分析代码,很明显`io/file`的返回值是函数的返回值,并且因为`io/file`的返回值是`java.io.File`,所以我们大概可以推测该函数的返回值本身也是`java.io.File`。
0

尽管在这个例子中这似乎很明了,一旦你引入条件语句/多个尾位置和原始类型,就变得相当复杂。存在多个尾位置时,真正答案是多个答案的情况是很常见的,在此情况下,可能需要找到一个共同的超类型或者省略。

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

目前,投入大量努力生成有限价值的成果可能不值得,但也许在未来可以关注一下。

...