请在2024 Clojure发展调查分享您的想法!

欢迎!有关此功能如何工作的更多信息,请参阅关于页面。

0 投票
编译器

在评估或编译clojure.lang.IType的实现者时,编译器尝试反射地访问其字段。当一个字段标记为可变(因此为私有)时,这会失败

`
Clojure 1.9.0-master-SNAPSHOT
user=> (deftype T [^:unsynchronized-mutable t])
user.T
user=> (T. :t)

object[user.T 0x2654635 "user.T@2654635"]

user=> (eval (T. :t))
编译器异常java.lang.IllegalArgumentException:未找到匹配字段:t

        Reflector.java:  271  clojure.lang.Reflector/getInstanceField
         Compiler.java: 4724  clojure.lang.Compiler$ObjExpr/emitValue
         Compiler.java: 4851  clojure.lang.Compiler$ObjExpr/emitConstants
         Compiler.java: 4529  clojure.lang.Compiler$ObjExpr/compile
         Compiler.java: 4049  clojure.lang.Compiler$FnExpr/parse
         Compiler.java: 6866  clojure.lang.Compiler/analyzeSeq
         Compiler.java: 6669  clojure.lang.Compiler/analyze
         Compiler.java: 6924  clojure.lang.Compiler/eval
         Compiler.java: 6890  clojure.lang.Compiler/eval
              core.clj: 3105  clojure.core/eval

...
`

对于未实现IType的类,不存在此问题。

`
user> (deftype* user/U user.U)

    [^:unsynchronized-mutable u]
    :implements [])


user> (eval (user.U. :u))

object[user.U 0x34699051 "user.U@34699051"]

`

此问题通常发生在为具有缓存的散列的deftype实现带标签的字面量时

2 答案

0 投票

评论者:alexmiller

是的,这很有趣。编译器将deftype编译为对构造函数的调用,并带上当前字段的值,但其可变字段不可访问。另一个选择可能是提供一些标准方法来“读取”字段集,而不是依赖于反射。(另一种选择是更改可变字段的访问修饰符,但我认为这可能是不切实际的。)

0 投票
参考:https://clojure.atlassian.net/browse/CLJ-2092(由bendlas报告)
...