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

欢迎!请访问关于页面,了解有关该功能的一些更多信息。

0
Clojure
重新标记

当一个非空队列被评估时,编译器不会尝试去执行它(就像对 Seq 执行的操作一样),而是将其视为 PersistentList,并因此发送到 clojure.lang.Compiler/emitListAsObjectArray。这是一个错误,因为队列不是列表。

=> (eval (conj clojure.lang.PersistentQueue/EMPTY 1)) 编译错误 (ClassCastException) 编译 fn* 在 (REPL:1:1)。类 clojure.lang.PersistentQueue 无法转换为类 java.util.List (clojure.lang.PersistentQueue 在未命名的模块 "app" 中;java.util.List 在模块 java.base 的加载器 "bootstrap" 中)

堆栈跟踪如下:

`
语法错误 编译 fn* 在 (1:1)。

at clojure.lang.Compiler.analyzeSeq(Compiler.java:7119)
at clojure.lang.Compiler.analyze(Compiler.java:6793)
at clojure.lang.Compiler.eval(Compiler.java:7178)
at clojure.lang.Compiler.eval(Compiler.java:7136)
at clojure.core$eval.invokeStatic(core.clj:3202)
at clojure.core$eval.invoke(core.clj:3198)
at user$eval242.invokeStatic(NO_SOURCE_FILE:1)
at user$eval242.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:7181)
at clojure.lang.Compiler.eval(Compiler.java:7136)
at clojure.core$eval.invokeStatic(core.clj:3202)
at clojure.core$eval.invoke(core.clj:3198)
at clojure.main$repl$read_eval_print__9110$fn__9113.invoke(main.clj:437)
at clojure.main$repl$read_eval_print__9110.invoke(main.clj:437)
at clojure.main$repl$fn__9119.invoke(main.clj:458)
at clojure.main$repl.invokeStatic(main.clj:458)
at clojure.main$repl_opt.invokeStatic(main.clj:522)
at clojure.main$main.invokeStatic(main.clj:667)
at clojure.main$main.doInvoke(main.clj:616)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.main.main(main.java:40)

原因:java.lang.ClassCastException:类 clojure.lang.PersistentQueue 无法转换为类 java.util.List (clojure.lang.PersistentQueue 在加载器 "app" 的未命名模块中;
java.util.List 在加载器 "bootstrap" 的模块 java.base 中)

at clojure.lang.Compiler$ObjExpr.emitListAsObjectArray(Compiler.java:4701)
at clojure.lang.Compiler$ObjExpr.emitValue(Compiler.java:4874)
at clojure.lang.Compiler$ObjExpr.emitConstants(Compiler.java:4938)
at clojure.lang.Compiler$ObjExpr.compile(Compiler.java:4616)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:4110)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:7109)
... 23 more`

1 答案

0

https://clojure.atlassian.net/browse/CLJ-2628记录,并提供了一些选项。

by
感谢您查看这个。我在票据的替代品上有一点评论。

- 如果 PersistentQueue 实现了 j.u.List,则会继续打印列表,即使这不是返回的内容。所以如果宏尝试返回一个队列(即使是在另一个 seq 中)它会被转换成列表。所以从宏中不可能返回一个队列。现在已经是这种情况了。
=> (defmacro m [] clojure.lang.PersistentQueue/EMPTY)
=> (m)
()
user=> (type (m))
clojure.lang.PersistentList$EmptyList

- 特化的 PQ 发射如何工作?

目前,emitValue 中的测试正在检查 ISeq 或 IPersistentList。只有两种类型实现了 IPersistentList:PersistentList 和 PersistentQueue。PersistentList 已经是一个 ISeq,所以对 IPersistentList 的检查就是这里问题的具体原因。去除它会让它通过到 RT.printString(value),这是大多数没有明确定义表示的对象也是通过的地方。

这引发了一个新的问题(这是一个我从别人那里转达的问题,但我自己也思考过了):是否考虑过队列的明确定义表示?
ClojureScript 有:#queue [1 2 3]
对于语言中内置的结构,可能值得为其自己的特殊读取宏。
这将为发出可以重新读取的结构提供一条途径。
by
>  如果 PersistentQueue 实现了 j.u.List,则会继续打印列表。

true,我没有考虑所有权衡,只是提出想法。

> 特化的 PQ 发射如何工作?

这个方法有很多,可以添加另一个。同样,没有更多的评估我就不知道权衡。


有一个关于队列的读取/打印支持的旧票据。

https://ask.clojure.org/index.php/3365/implement-reader-literal-support-persistentqueue-structure

我自问的问题是,队列是否足够重要,值得在 Clojure 中添加语法。我没有好的答案——这最终不是我的决定。:)但任何关于此的具体评论都可以放在那里。
...