2024 Clojure 状况调查 中分享你的想法!

欢迎!请访问关于页面了解更多关于该网站的信息。

0
错误
已关闭

问题陈述

clojure.core/deref 函数被非 clojure.lang.IDerefjava.util.concurrent.Future 实例的对象调用时,会抛出一个难以理解 ClassCastException。在我的经验中,在接纳新 Clojure 用户(在我的工作和开源项目中),这种情况经常出现并且可能相当令人困惑,因为它没有在代码中指向任何明显的地方。即使有了堆栈跟踪,它仅指向 deref-future 的定义(而不是函数体中的某个特定行),这进一步增加了困惑。

讨论

在 Slack 上,我建议将 deref 的实现更改为类似 (cond (instance? clojure.lang.IDeref ref) ... (instance? java.util.concurrent.Future ref) ... :else (throw (IllegalArgumentException (str ref " cannot be deref'd as it is of type " (class ref) "."))) 的形式。

Sean Corfield 提到,这样的修复将影响所有非-IDeref 的 deref 使用性能,我承认这一点但觉得可以接受。

重现

user=> (def a {})
#'user/a

user=> @a
Execution error (ClassCastException) at user/eval22861 (REPL:0).
class clojure.lang.PersistentArrayMap cannot be cast to class java.util.concurrent.Future (clojure.lang.PersistentArrayMap is in unnamed module of loader 'app'; java.util.concurrent.Future is in module java.base of loader 'bootstrap')

user=> (pst)
ClassCastException class clojure.lang.PersistentArrayMap cannot be cast to class java.util.concurrent.Future (clojure.lang.PersistentArrayMap is in unnamed module of loader 'app'; java.util.concurrent.Future is in module java.base of loader 'bootstrap')
    clojure.core/deref-future (core.clj:2315)
    clojure.core/deref-future (core.clj:2315)
    clojure.core/deref (core.clj:2338)
    clojure.core/deref (core.clj:2323)
    user/eval22863 (NO_SOURCE_FILE:0)
    user/eval22863 (NO_SOURCE_FILE:-1)
    clojure.lang.Compiler.eval (Compiler.java:7194)
    clojure.lang.Compiler.eval (Compiler.java:7149)
    clojure.core/eval (core.clj:3215)
    clojure.core/eval (core.clj:3211)
    clojure.main/repl/read-eval-print--9206/fn--9209 (main.clj:437)
    clojure.main/repl/read-eval-print--9206 (main.clj:437)
看起来这好像是一个重复的提问https://ask.clojure.org/index.php/1553/error-message-when-calling-deref-on-non-ideref-is-unhelpful,不幸的是在我发表后才发现。
谢谢,我也没有找到,尽管在ask和jira上搜索过,我会将这个问题标注为重复。
...