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

欢迎!请参阅 关于 页面以获取更多关于此功能的 Informationen。

0 投票
ClojureScript
已关闭

你好,
我发现了一些关于 sorted-map 的奇怪行为,这对我来说像是一个错误或者文档不足。

具体来说,当创建具有不同类型键的排序映射,例如这样:(sorted-map :k1 :v1 "k2" :v2),然后像这样查找:(:k1 (sorted-map :k1 :v1 "k2" :v2)) 产生异常:无法比较 k2 与 :k1。这看起来是因为在 sorted-map 实现中使用了 compare

虽然(对我来说)更合理的做法是全面支持异构键,但似乎有理由要求排序映射的键是可比较的,但在我个人意见中,这一点应该在 文档 中声明。

即使这是要求,我认为与 Clojure 的总体设计精神更一致的做法是在这样的查找时返回 nil,而不是抛出异常。对于在映射中添加无法与其他键比较的键时抛出异常的做法,我会觉得更有意义。你怎么看?

谨致问候,
Simon

在插入元素时尝试抛出异常,将需要扫描地图中的所有现有元素以验证它们是否可以与您要插入的元素进行比较,这对性能和可扩展性非常不利。同样,当您引发比较并在翻译时捕获异常,这将增加每次正确使用地图都会浪费的开销。这并不是Clojure中唯一需要了解涉及的数据结构实际合同并在使用时正确使用它们或最终得到意外结果,以性能为代价的情况。(更不用说,还需要特殊面向Clojure的Java类的全部实现来添加这些功能。)

在这种情况下,涉及的数据结构是Java的`SortedMap`接口。以下是JavaDoc的第二个段落

插入到有序映射中的所有键必须实现`Comparable`接口(或由指定的比较器接受)。此外,所有此类键必须可以相互比较:`k1.compareTo(k2)`(或`comparator.compare(k1, k2)`)对于有序映射中的任何键`k1`和`k2`都不能抛出`ClassCastException`。尝试违反此限制将导致引发`ClassCastException`的受影响的方或构造函数调用。

随着你对JVM Clojure的了解深入,不可避免地需要了解它构建在哪个Java类库上以及与之交互的细节。话虽如此,从Clojure文档中链接此JavaDoc并或许将其总结/翻译成Clojure术语可能会很有用。
我对导致行为成为这样的非常实际的论点表示赞赏,并对它们表示尊重。

关于开发人员体验和改进语言采用问题,尤其是与Clojurescript相关的,我会重申我在回复Alex时提到的观点:存在“Comparable”JVM合同是相当隐晦且难以在工作中主要使用Clojurescript的人发现。我会建议从排序映射文档中指向它。


我认为这样的合同在多大程度上应该是“直观”是非常主观的,取决于每个开发者的背景;作为一个不同视角:假设我可以从映射中获取到我成功插入的每一对,这似乎是完全合理的。更进一步,即使可以直观地意识到为了在有序映射上启用assoc和get, giữa tất cả các từ khóa phải có một thứ tự, việc người dùng có thể assoc các từ khóa của các loại khác nhau trong sự缺席其他任何文档的情况下,会加强(不正确的)信念,即默认比较器确实能够在不同类型之间提供顺序。
我想明确表示,我听到了你的话,理解了,并对你的困惑和挫败感表示同情!在文档中尽力指出这些问题希望有所帮助,但我仍预计人们可能会在这些问题上跌倒。我知道我确实有过这样的经历,而且有时即便我已经拥有Java背景,还会有这样的情况。试图在庞大生态系统中构建一个具有自己历史和不同哲学的统一、优秀的语言是一项巨大的挑战。
试图在庞大生态系统中构建一个具有自己历史和不同哲学的统一、优秀的语言是一项巨大的挑战。

我非常赞同,即便是在完全拥有两个系统的情况下,保持一致性也是一项挑战。Clojure能够在两个(或更多)具有悠久历史遗产的生态系统之上建立一致的语言,这是对它深思熟虑的证明,我对此表示赞赏。

1 个回答

0 投票

这是预期的行为(与在根据comparator按顺序排列的map中查找键时Java的行为相匹配,该comparator不能处理查找键类型)。


编辑
谢谢您的快速回复!
作为一个从Clojurescript进入Clojure生态系统的人,我的 Clojure 和 Java 背景都很有限,这真的很不直观(因为语言的其他部分设计得很逻辑,且旨在最小化意外)。

您是否会考虑在sorted-map文档中解释这种行为?

例如,“sorted-map会允许你使用异构键进行assoc,但不允许查找。这与Java在根据comparator排序的map中查找键并处理不了查找键类型时的行为相匹配)。
...