2024 State of 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 定义的相同类型。
调用类型的相关方法,并将返回值用作 (= 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 集合都会为 Clojure 持久集合的等价和 Java 互操作实现耶quiv 和 equals。它们还实现了 hasheq 用于自定义哈希。它们也为这些函数提供了特殊的工具函数(hash-unordered-collection 和 hash-ordered-collection),这些函数使用 murmur3 实现与 Clojure 现有集合一致的习语式哈希。关于相等,有很多东西可能会变得有些棘手。
更多详细信息,请参阅 https://clojure.org/guides/equality
...