欢迎!请参阅关于页面获取更多关于如何操作的信息。
(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。你觉得呢?
println
local-dir
io/file
java.io.File
调查Clojure源代码
关键函数是hasJavaClass和getJavaClass。 https://github.com/clojure/clojure/blob/8c8e4f6ef21f3d0f59deb60cdc7e1b584f596d59/src/jvm/clojure/lang/Compiler.java#L359-L361
hasJavaClass
getJavaClass
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
local-dir实际返回的是Object,因为在Clojure中没有返回类型提示的所有函数都是如此。这里没有推断。
Object
你可以这样标记返回类型为File:(defn- local-dir ^java.io.File [] ..)
File
(defn- local-dir ^java.io.File [] ..)
这样就不会有反射。
尽管在这个例子中这似乎很明了,一旦你引入条件语句/多个尾位置和原始类型,就变得相当复杂。存在多个尾位置时,真正答案是多个答案的情况是很常见的,在此情况下,可能需要找到一个共同的超类型或者省略。
此外,由于类型提示主要用于Java互操作性,实际上需要返回类型提示的情况相对较小(许多程序可能不存在这种情况)。
目前,投入大量努力生成有限价值的成果可能不值得,但也许在未来可以关注一下。