序列集合的Clojure等式 P>我注意到Culjule(1.4)似乎很乐意考虑向量相同于相同向量的 SEQ < /代码>,但同样不适用于图: (= [1 2] (seq [1 2])) => true (= {1 2} (seq {1 2})) => false
为什么序列集合的Clojure等式 P>我注意到Culjule(1.4)似乎很乐意考虑向量相同于相同向量的 SEQ < /代码>,但同样不适用于图: (= [1 2] (seq [1 2])) => true (= {1 2} (seq {1 2})) => false,clojure,sequence,equality,Clojure,Sequence,Equality,为什么=的行为应该以这种方式有所不同?我想这是因为序列顺序以及特定位置的值都很重要,而在map中键/值的顺序并不重要,语义之间的这种差异导致了这一点,如示例代码所示 有关更多详细信息,请查看文件中的mapEquals 它检查另一个对象是否映射,然后返回false。在我看来,这个示例指出了clojure中值相等的概念中的一点不一致,在这种情况下,它们是从同一类型派生的不同类型(通过seq函数)。可以很好地说,这并不矛盾,因为它将派生类型与派生类型进行比较,我可以理解,如果使用向量将相同的逻辑应用于
=
的行为应该以这种方式有所不同?我想这是因为序列顺序以及特定位置的值都很重要,而在map中键/值的顺序并不重要,语义之间的这种差异导致了这一点,如示例代码所示
有关更多详细信息,请查看文件中的mapEquals
它检查另一个对象是否映射,然后返回false。在我看来,这个示例指出了clojure中值相等的概念中的一点不一致,在这种情况下,它们是从同一类型派生的不同类型(通过
seq
函数)。可以很好地说,这并不矛盾,因为它将派生类型与派生类型进行比较,我可以理解,如果使用向量将相同的逻辑应用于相同的示例(请注意底部)
user=> (seq {1 2})
([1 2])
user=> (type {1 2})
clojure.lang.PersistentArrayMap
内容类型相同:
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)
但它们并不平等
用户>(={12}(seq{12}))
假的
对于较长的地图也是如此:
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)
即使它们的顺序不同:
但是,如果包含的类型不同,则情况也不同:-(
编辑:这并不总是正确的,请参见以下内容:
为了解决这个问题,您可以在比较之前将所有内容转换为seq,这(我认为)是安全的,因为seq函数总是以相同的方式迭代整个数据结构,并且结构是不可变的值,seq的seq
是seq
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
也许理解这些细微的不一致是学习一门语言的一部分,或者有一天这可以改变(尽管我不会屏住呼吸)
编辑:
我发现两个映射为同一个值生成不同的序列,因此仅在映射上调用seq不会给您提供正确的映射等式:
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
下面是一个我称之为适当映射平等的示例:
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
Clojure的=
可以看作是通过两个步骤进行比较:
检查被比较对象的类型是否属于同一个“相等分区”,即其成员可能相等的一类类型(取决于给定数据结构的确切成员,而不是分区中的特定类型)
如果是这样,检查被比较的事物是否是相等的
一个这样的等分是“连续”事物的等分。向量被认为是连续的:
(instance? clojure.lang.Sequential [])
;= true
各种类型的序列号如下:
(instance? clojure.lang.Sequential (seq {1 2}))
;= true
因此,当(且仅当)向量的对应元素相等时,认为向量等于序列
(请注意,(seq{})
产生nil
,它不是顺序的,并将“不等于”与(
,[]
等进行比较。)
另一方面,映射本身构成了一个相等分区,因此,虽然哈希映射可能被视为等同于已排序的映射,但它永远不会被视为等同于seq。特别是,它不等同于其条目的seq,而seq正是(seq some map)
产生的结果。(seq some hash map)
提供一系列条目(键/值对)
例如:
foo.core=> (seq {:a 1 :b 2 :c 3})
([:a 1] [:c 3] [:b 2])
这与[:a1:b2:c3]
不同