Clojure 2024 年调查问卷 中分享您的想法!

欢迎!请参阅 关于 页面了解有关此处的更多信息。

0
Collections

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

有关此主题在 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()进行比较,并且确实具有相同的.hashCode()。

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集合-这种情况本身并不存在于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用于非值时抛出错误。这将导致哈希类型的更清晰分离。当然,这将防止将非值放入hash-set中。

0

评论由:alexmiller 提供

不过,没有简单的"valueness"检查吗?

0

评论由:jafingerhut 提供

一个想法,如果有什么价值的话:在 Util.hasheq 方法中增加一个 java.util.Collection 实例的测试,而不是为 Set、List 和 Map 分别增加 3 个单独的测试。这没有涵盖 Map.Entry。

0

评论由:alexmiller 提供

Map 也不扩展 Collection。

...