请分享您的想法,参加2024年Clojure状态调查!

欢迎使用!有关更多信息,请参阅关于页面。

+1

这看起来像是ClojureScript 1.11.54中的一个bug

(conj {} [:a 1] '([:b 2] [:c 3]) '([:d 4]))

在JVM上的Clojure中这是一个错误

cljs.user> (conj {} [:a 1] '([:b 2] [:c 3]) '([:d 4]))
{:a 1, :b 2, :c 3, :d 4}
cljs.user> :cljs/quit
nil
user> (conj {} [:a 1] '([:b 2] [:c 3]) '([:d 4]))
Execution error (ClassCastException) at user/eval17754 (REPL:25).
class clojure.lang.PersistentVector cannot be cast to class java.util.Map$Entry (clojure.lang.PersistentVector is in unnamed module of loader 'app'; java.util.Map$Entry is in module java.base of loader 'bootstrap')
某物之所以“可行”,并不意味着它是一个bug。这也不意味着它是预期行为,可以依赖。在这种情况下,可能只是一次偶然。
在这种情况下,使代码可行几乎没有从数据角度来看的意义。

Conj可以精确地将两个元素的向量添加到映射中。不应该将向量的列表连接。

换句话说,(conj {} [[:a 1] [:b 2]])很好,因为我们正在连接两个向量的向量,结果为{[:a 1] [:b 2]}。

然而,(conj {} '([:a 1] [:b 2]))不应该好,因为它不是一个向量。

而将'([:d 4])仅添加到映射中则完全没有意义,也不应该起作用,但它在CLJS中确实如此。特别是[[:d 4]]的连接不起作用。

CLJS几乎不考虑它是元素的列表还是只是元素


=> {[:a 1] [:b 2], :c 3, :d 4}
某事物以特定方式正常工作并不一定有意义。如果某事物没有文档记录,根据定义,它就是未定义的行为。"不应该行得通" - 确实不行得通,如果它没有记录的话。并不是每个无效或未定义的行为都会抛出异常,特别是在Clojure[Script]中。
>> 如果某事物没有文档记录,根据定义,它就是未定义的行为。

其实恰好相反。语言规定未定义行为应该是不可预知的。这就是我们知道它是一种不应该依赖的未定义行为,但它不是一个bug。

你的说法是不确定的行为了,这通常是由于在文档或实现中忽略了一些内容造成的。在这种情况下,我怀疑是后者的原因。

我不知道你为什么试图减轻这个问题,如果这是一个编译器的bug,那么它可能是在协议实现中,这可能是一个严重的问题。
>> 未定义行为被语言规定为不可预知的

如果你读过更多与核心团队的讨论,通常未记录的被视为未定义的。至少根据我的理解和记忆,他们是这样看待问题的。
例如,请参阅Sean Corfield的这个好评论:https://groups.google.com/g/clojure/c/yMHHHuK44pE/m/LeBhqdq6BQAJ
或者Alex Miller的这篇明确讨论了特定事项缺乏文档中的未定义行为的问题:https://groups.google.com/g/clojure/c/VwA2Un2NMxc/m/tptww3xZBwAJ
或者这个:https://groups.google.com/g/clojure/c/HtK4pqsr--8/m/KbWvq8CFCQAJ
以及许多许多其他评论,遍布各个媒体。

>> 不确定的行为了

Clojure留下了很多不确定的东西。语言自身没有任何规范或标准,只有文档(并不记录所有存在的事物),一些规范定义和参考实现。已经被明确表示,详细说明并不是目标。

例如,调用 `keys`、`vals` 或遍历相同的 map 对象将返回相同的顺序。但是,与第一个等价的另一个 map 对象可能会有不同的顺序。在 CLJS 中,map 对象很可能返回的顺序与 CLJ 中不同。

如果这是编译器中的错误,它可能存在于协议实现中,这可能是一个严重的问题。

如果是这种情况,那就另当别论了。

登录注册以回答此问题。

...