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

欢迎!请查看 关于页面 了解更多关于它是如何工作的信息。

0
Clojure

我有两个序列 'a' 和 'b'。它们的长度相同,并且它们的对应元素通过 '=' 比较是相等的。但是,如果将这两个序列传递给 '=',结果却是 false

(doseq [[x y] (zip-colls a b)]
  (println (= x y)))
true
true
true
true

(count a)
4
(count b)
4

(= a b)
false

这与 Clojure 的等价法则相矛盾

当使用两个集合调用 Clojure 的 '=' 时,如果

两个参数都是顺序的(序列、列表、向量、队列或实现 java.util.List 的 Java 集合),并且相同的顺序中有相等元素。

我正在比较这个类的两个实例:https://github.com/fctorial/parse_struct/blob/master/src/clojure/lang/ROVec.java

1 答案

0

已被选中
 
最佳答案

这就是你的问题所在

如果对象实现了 equiv,它会被 '=' 识别。

对于所有其他类型
两个参数均为使用 deftype 定义的同一种类型。
调用类型的equiv方法,其返回值成为 (= x y) 的值。
对于其他类型,Java 的 x.equals(y) 为 true。

我敢打赌,如果您在它们的序列强转上进行 '=' 比较,您会发现序列是相等的...

(deftype wrapper [xs] 
   clojure.lang.IPersistentCollection 
   (equiv [this that] false) 
   clojure.lang.Seqable 
   (seq [this] (seq xs)))

user=> (let [xs (wrapper. [1 2 3]) 
             ys (wrapper. [1 2 3])] 
         [(= xs ys) (= (seq xs) (seq ys))])
[false true]
这很尴尬。我在这份文件中确实搜索了'equals'。
大多数Clojure集合将实现equiv和equals,以便于Clojure持久化集合的等价性和Java互操作性。它们还实现了hasheq以进行自定义哈希处理。为此还提供了特殊的工具函数(hash-unordered-collection和hash-ordered-collection),这些函数使用murmur3算法进行哈希,以提高与Clojure现有集合的哈希一致性。有关等价性的内容有很多,有时可能会令人困惑。
对于更详细的说明,请参阅https://clojure.org/guides/equality
...