Clojure集合与序列的相等性

mik*_*era 5 equality clojure sequence

我注意到Clojure(1.4)似乎很乐意考虑等于seq同一向量的向量,但同样不适用于地图:

(= [1 2] (seq [1 2]))
=> true

(= {1 2} (seq {1 2}))
=> false
Run Code Online (Sandbox Code Playgroud)

为什么这种行为=会有所不同?

Mic*_*zyk 12

Clojure =可以被认为是通过两个步骤进行比较:

  1. 检查被比较的东西的类型是否属于相同的"相等分区",即一类类型的成员可能相等(取决于给定数据结构的确切成员,但不是特定类型)分区);

  2. 如果是,请检查实际比较的内容是否相等.

一个这样的平等分区是"顺序"事物.向量被认为是顺序的:

(instance? clojure.lang.Sequential [])
;= true
Run Code Online (Sandbox Code Playgroud)

以及各种类型的seqs:

(instance? clojure.lang.Sequential (seq {1 2}))
;= true
Run Code Online (Sandbox Code Playgroud)

因此,如果(并且仅当)它们的对应元素相等,则认为向量等于seq.

(需要注意的是(seq {})产生nil,这是连续的,并比较"不等于"到(),[]等等)

另一方面,映射构成了它们自己的相等分区,因此虽然哈希映射可能被认为等于有序映射,但它永远不会被认为等于seq.特别是,它不等于其条目的seq,这是(seq some-map)产生的.


Ank*_*kur 5

我想这是因为在序列顺序以及特定位置的值很重要,因为在映射中键/值的顺序无关紧要,语义之间的这种差异导致它按照示例代码所示工作.

有关详细信息,请参阅mapEquals文件https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/APersistentMap.java

它检查另一个对象是否不是map,然后返回false.