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

欢迎!请参阅关于页面以获取更多关于如何使用本站的信息。

0
编译器

持久队列对象在编译器中没有遵循正确的评估路径。

最简单的情况

user=> (def q (conj clojure.lang.PersistentQueue/EMPTY 1 2 3))

'user/q

user=> q

user=> (eval q)
CompilerException java.lang.ClassCastException: clojure.lang.PersistentQueue cannot be cast to java.util.List, compiling:(NO_SOURCE_PATH:4:1)

当嵌入持久队列时,也会遇到相同的异常

user=> (eval `(fn (link: ) ~q))
CompilerException java.lang.ClassCastException: clojure.lang.PersistentQueue cannot be cast to java.util.List, compiling:(NO_SOURCE_PATH:2:1)

Expected result 而不是

CompilerException java.lang.RuntimeException: Can't embed unreadable object in code: #, compiling:(NO_SOURCE_PATH:3:1)

由于 PersistentQueue 实现了 IPersistentCollection 和 IPersistentList,并且编译器中未明确提及,因此它陷入了与列表相同的编译路径。异常来自 FnExpr 中 emitValue 部分的 emitConstants 调用。PersistentQueue 未实现 java.util.List,因此在 emitListAsObjectArray (Compiler.java:4479) 中抛出异常。但是,实现 List 并不能解决这个问题,而是通过将所有评估过的持久队列编译为持久列表来遮掩这个问题。

第一种情况通过向 Compiler.eval() 的 IPersistentCollection 分支添加 && !(form instanceof PersistentQueue) 得到解决,允许持久队列自动降至 analyze (Compiler.java:6459) 中的 ConstantExpr 情况。嵌入情况通过向 ObjExpr 的 emitValue 的 IPersistentList 分支添加 && !(value instanceof PersistentQueue) 得到解决。

此错误还阻止了为 PersistentQueue 定义词法读取器,因为在将读取的对象传递到编译器时抛出了异常。

提供的补丁包含了上述两个更改,并对每个情况进行了测试,以说明该错误。

Clojure-dev 线程:https://groups.google.com/forum/#!topic/clojure-dev/LDUQfqjFg9w

1 答案

0
...