请在Clojure 2024状态调查!分享你的想法。

欢迎!请查看关于页面以了解更多此流程的信息。

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,它将被 pick up by .

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

我敢打赌,如果你比较它们的seq强制转换上的=,你会发现序列是=...

(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
...