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 运行时发生错误。
我看不到这两个调用的区别,并且由于显然 io/filelocal-dir 的返回值,它应该推断为 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 交互,因此真正需要返回类型提示的情况相对较少(许多程序可能没有此类情况)。

目前,生产有限用途所需的努力可能不值得,但未来可能值得一看。

...