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

欢迎!请查看 关于 页面,了解更多关于这个网站的信息。

0
Java 协议

下面是一个示例代码

(set! *warn-on-reflection* true)
(defn hello ^String []
  "hello")
(def a (hello))
(.replace a \e \a)

;;> Reflection warning, NO_SOURCE_PATH:1:1 - call to method replace can't be resolved (target class is unknown).
;;=> "hallo"

正如我们所见,Clojure 似乎无法推断 Var a 的类型,即使函数 (hello) 有返回类型提示。

如果 Clojure 能够推断这一点,那将是很好的。否则,目前,用户必须显式提供类型提示。

1 答案

0

这是一些看似简单但越深入探索越复杂的事情之一。

Vars 本质上是盒子,可以承载任何类型的对象。您可以通过以下方式轻松更改这里所持有的值的类型

(alter-var-root a (constantly 100))

这将使类型提示“错误”。

本身 hello 是一个变量,它包含一个具有该返回类型的函数。那么,在您调用它之前,如果它被重新绑定到具有不同类型提示的对象会发生什么呢?

另一种情况是多参数函数,其中不同的参数返回不同类型的对象。

毫无疑问,还有其他一些类似原始类型、直接链接等也会产生影响的因素。

by
是的,我想这可能是很难添加的,虽然这么做会很不错。

我想在绑定时添加类型提示可能更合适。当 var 的值被设置时,其类型就知道了,我们可以用这个类型更新 var 元数据。尽管我认为这可能会减慢 def 的运行速度,因为 def 已经负责了很多启动慢的问题。就像 def 能够抓取值的类型并用它更新 Var 元数据。

如果在编译时完成,我不知道是否需要担心 alter-var-root 的问题。这似乎是一个边缘情况,错误的提示只是回退到反射,不是吗?但似乎在大多数情况下,提示是正确的。

def 不在评估时被编译吗,所以在这之间改变 hello var 似乎不可能,或者如果 hello var 在之前改变,这无关紧要,当我们到达 def 时,它就会使用 hello 的最新值的类型提示。
...