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的'='当用两个收集项调用时为true,如果

两个参数都是顺序型(序列、列表、向量、队列或实现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。

我敢打赌,如果您比较他们的seq coercions的'=',您会发现序列是相等的...

(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已有集合的惯用哈希。在等价性方面有很多内容可能很棘手。
...