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

欢迎!请查阅关于页面以了解更多关于此工作的信息关于

投票数 0
集合

c.c/hash在比较Clojure集合时始终使用hashCode,而Clojure集合使用Murmur3,导致不兼容。

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添加一个特殊案例,就像现在为String那样。

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

43 答案

投票数 0

评论者:wagjo

对于map也有相同的问题,因此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()比较,并且确实具有相同的.hashCode()。

投票数 0

评论者:wagjo

如果没有补丁,以下声明将不成立:“如果两个对象通过c.c/=相等,那么它们通过c.c/hash返回的哈希码是相同的数字”。我们只能说当两个对象都是'clojure'对象时,这是成立的,但这与clojures的交互原则(交互简单、快速、无惊喜)相矛盾。

投票数 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次这种发生的类(请注意,其中恰好0个是Java集合——这种情况本身不存在于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的路径中添加更多的instanceof检查。这也很可能导致任何JVM内联失败。

Rich表示“对于非值型的hasheq/equiv,一切赌注都应该取消”,而Java集合显然属于“非值型”。

投票数 0

评论者:jafingerhut

是否应考虑文档修补方案?例如,修改clojure.core/hash的文档,加入一句话表明它只保证与clojure.core/=对于不可变值的兼容性?甚至还可以提及浮点数的例外:参见CLJ-1036。

投票数 0

评论者:alexmiller

我认为,应优先在

投票数 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

对不起打扰你,但可能还有另一个选项,即在non-values请求hasheq时不要回退到hashCode,而是抛出异常。这将导致hash类型之间的更清晰分离。当然,这将防止将非值放入hash-set。

投票数 0

评论者:alexmiller

尽管如此,没有简单的“值存在”检查吗?

投票数 0

评论者:jafingerhut

一个想法,即使它可能没有价值:在Util.hasheq方法中添加一个对java.util.Collection实例的测试,而不是对Set、List和Map进行的三个独立测试。这并不覆盖Map.Entry。

投票数 0

评论者:alexmiller

Map也不扩展Collection。

欢迎使用Clojure问答社区,您在这里可以提出问题并从Clojure社区的成员那里获得答案。

类别

...