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

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

0
集合

c.c/hash总是使用java集合的hashCode方法,这在与使用Murmur3的Clojure集合比较时是不兼容的。

user=> (== (hash (java.util.ArrayList. [1 2 3])) (hash [1 2 3])) false user=> (= (java.util.ArrayList. [1 2 3]) [1 2 3]) true

一种修复方法是向 Util/hasheq 中添加一个针对java.util.Collections的特殊情况,就像现在的字符串一样。

关于这个主题在Clojure组中的讨论链接: https://groups.google.com/forum/#!topic/clojure/dQhdwZsyIEw

43 个答案

0

评论由:wagjo

对于映射同样有问题,因此hasheq也应该对java.util.Map有特殊情况。

0

评论由:wagjo

增加了针对j.u. Map, Set和List的修复补丁。

0

评论由:jafingerhut

添加补丁clj-1372-2.diff,它与Jozef Wagner的clj-1372.diff相同,只不过它还添加了一些在没有他的更改的情况下失败、在有他的更改时通过的新测试。

0

由 alexmiller发表的评论:

我认为equiv/hasheq的合约比这更为狭窄,并且仅当两个集合都是IPersistentCollection的时候才适用。换句话说,我认为这不是所需要的或必须的。

请注意,这里的Java .equals/.hashCode合约确实被维护 - 这些集合将通过.equals()进行比较,并且具有相同的.habbo()。

0

评论由:wagjo

在没有补丁的情况下,以下陈述是无效的:"如果两个对象在c.c/=中相等,那么c.c/hash返回的哈希值是相同的数字"。我们只能说,只有在两个对象都是'clojure'对象的情况下,这是有效的,但这与 clojure 的互操作原则相违背(互操作简单,快捷,没有意外)。

0

评论由:wagjo

此错误的体现:

user=> (assoc (hash-map [1 2 3] :foo) (java.util.ArrayList. [1 2 3]) :bar) {[1 2 3] :bar, [1 2 3] :foo} user=> (get (hash-map [1 2 3] :foo) (java.util.ArrayList. [1 2 3])) nil

0

由 alexmiller发表的评论:

我同意这将是很好的一句话,无需任何限定。

在hasheq中添加更多分支确实会带来实际的成本 - 添加这些集合检查会影响所有的hasheq。运行完整的Clojure构建,我看到以下一系列类,其中大于100次发生这种情况(注意,这些Java集合中正好有0个——这种情况本身不存在于Clojure构建中)

clojure.lang.Var 107001502 java.lang.Class 2651389 java.lang.Character 2076322 java.util.UUID 435235 java.util.Date 430956 clojure.lang.Compiler$LocalBinding 116830 java.lang.Boolean 112361 java.util.regex.Pattern 325

我们将在每个hasheq的路径中添加4个额外的instanceof检查。这也可能会破坏任何JVM内联。

Rich说 "hasheq/equiv的非值应该没有任何保证",而Java集合显然是"非值"类。

0

评论由:jafingerhut

是否应考虑文档修补程序?比如修改 clojure.core/hash 的文档,包含一个表明它仅保证与 clojure.core/= 兼容的不可变值的短语?甚至可能还提到浮点数也不适用:查看 CLJ-1036。

0

由 alexmiller发表的评论:

我认为最好在 https://clojure.org/data_structures 中编写有关哈希的详细文档,而不是在文档字符串中。尽管哈希函数的文档字符串可能需要更新,并指向最新的网站修改后。

0

评论由:wagjo

尽管这是一个从 1.5 版本开始的重大更改,但应在变更日志中提及。仍然让我困扰的是,c.c/= 在这些情况下被支持,但 c.c/hash 没有被支持。如果支持 c.c/hash 是昂贵的,那么不在此类情况下支持 c.c/= 不是更好吗?这将消除如下的意外:

user=> (apply distinct? (hash-set [1 2 3] (java.util.Collections/unmodifiableList [1 2 3]))) false

0

由 alexmiller发表的评论:

我不确定如果不考虑保证变更的话是否真的算是“重大更改”。 :) 但我理解你的观点。

我认为不可能放弃 Clojure 和 Java 集合对等性的支持——这看起来很重要且有用。如果这样做是免费的,我将希望能够无条件的说明,如果equiv=true,则 hasheq 相同。

在我看不清的问题是此票上的示例确实可能是人们可能遇到的真正问题。hasheq 的主要用户是哈希表和哈希集。因此,为了表现出来,您需要将 Clojure 和 Java 集合混合放入其中一个中,尤其是比较相等的集合混合。

还在思考这个问题。

0

评论由:wagjo

没关系发邮件打扰,但是可能还有另一种选择,不是将 hasheq 中的回退到 hashCode,而是当请求非值 hasheq 时抛出异常。这将导致更清晰的哈希类型的分离。当然,它会阻止将非值放入哈希集中。

0

由 alexmiller发表的评论:

然而,是否存在对“值得性”的简单检查?

0

评论由:jafingerhut

一个想法,如果不是无价值的:在 Util.hasheq 方法中添加一个对 java.util.Collection 实例的测试,而不是为 Set、List 和 Map 分别添加 3 个独立的测试。它不涵盖 Map.Entry。

0

由 alexmiller发表的评论:

Map 也不扩展 Collection。

...