与序列集合Clojure的平等(Clojure equality of collections wi

2019-09-18 01:15发布

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

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

(= {1 2} (seq {1 2}))
=> false

的行为,为什么要=在这种方式有什么不同?

Answer 1:

Clojure的=可以被认为是分两步进行的比较:

  1. 检查的事物的类型是属于同一个“平等分区”相比,这是一个类的类型,其成员可能潜在地等于(取决于事情,比如给定的数据结构的具体成员,而不是特定类型的的分区);

  2. 如果是这样,检查是否实际被比较的东西都是平等的。

这样一个平等的分区是,“连续”的事情。 载体是考虑顺序:

(instance? clojure.lang.Sequential [])
;= true

由于有各类seqs:

(instance? clojure.lang.Sequential (seq {1 2}))
;= true

因此,如果(且仅当)及其相应的元素相等的矢量被认为等于一个起。

(请注意, (seq {})产生nil ,这是连续的,并比较“不等于”至() []等)

在另一方面,地图构成了自己的平等分区,所以当一个哈希地图可能被认为等于有序映射,它永远不会被视为等于起。 特别是,它不等于其条目的SEQ,这是什么(seq some-map)产生。



Answer 2:

我想这是因为在序列顺序以及在特定位置值,其中重要的在地图键/值的顺序并不重要和语义之间的这种差异导致如图示例代码这个工作。

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

它检查,如果其他对象没有映射则返回false。



Answer 3:

user=> (seq {1 2})
([1 2])
user=> (type {1 2})
clojure.lang.PersistentArrayMap


Answer 4:

在我看来,这个例子指出,在这种情况下,他们是来自同一个类型(由派生不同类型Clojure中值的平等的观念稍有不一致seq功能)。 它很可能是认为,这是因为它是一个派生类型进行比较来衍生它的类型和我可以理解,如果相同的逻辑应用于此相同的例如使用载体(注意在底部)是不矛盾的

内容是相同的类型:

user> (type (first (seq {1 2})))
clojure.lang.MapEntry
user> (type (first {1 2}))
clojure.lang.MapEntry

user> (= (type (first {1 2})) (type (first (seq {1 2}))))
true
user> (= (first {1 2}) (first (seq {1 2})))
true

序列具有相同的值

user> (map = (seq {1 2}) {1 2})
(true)

但它们不被认为等于用户>(= {1 2}(SEQ {1 2}))假

这是一个较长的地图也是如此:

user> (map = (seq {1 2 3 4}) {1 2 3 4})
(true true)
user> (map = (seq {1 2 3 4 5 6}) {1 2 3 4 5 6})
(true true true)
user> (map = (seq {9 10 1 2 3 4 5 6}) {9 10 1 2 3 4 5 6})
(true true true true)    

即使它们不是在同一顺序 :

user> (map = (seq {9 10 1 2 3 4 5 6}) {1 2 3 4 5 6 9 10})
(true true true true)

但又不如果包含类型不同:-(

user> (= {1 2 3 4} (seq {1 2 3 4}))
false

编辑:这并不总是正确见下文:要解决这一点,你可以比较 ,这是(我相信)安全的,因为SEQ函数总是遍历整个数据结构以同样的方式和结构是不变的值之前,一切都转换为SEQ和seq一的seqseq

user> (= (seq {9 10 1 2 3 4 5 6}) {1 2 3 4 5 6 9 10})
false
user> (= (seq {9 10 1 2 3 4 5 6}) (seq {1 2 3 4 5 6 9 10}))
true


矢量的处理方式不同:

user> (= [1 2 3 4] (seq [1 2 3 4]))
true

也许理解轻微不一致是可以改变的(虽然我不认为我的呼吸)学习语言或者这一天的一部分


编辑:

我发现了两个产生了相同的值不同的序列,以便只在地图上的调用序列不会给你适当的地图平等地图:

user> (seq (zipmap  [3 1 5 9][4 2 6 10]))
([9 10] [5 6] [1 2] [3 4])
user> (seq {9 10 5 6 1 2 3 4})
([1 2] [3 4] [5 6] [9 10])
user> 

这里是我打电话给适当的地图平等的例子:

user> (def a (zipmap  [3 1 5 9][4 2 6 10]))
#'user/a
user> (def b {9 10 5 6 1 2 3 4})
#'user/b
user> (every? true? (map #(= (a %) (b %)) (keys a)))
true


Answer 5:

(seq some-hash-map)让你条目(键/值对)的序列。

例如:

foo.core=> (seq {:a 1 :b 2 :c 3})
([:a 1] [:c 3] [:b 2])

这是不一样的[:a 1 :b 2 :c 3]



文章来源: Clojure equality of collections with sequences