Clojure中的地图和记录相等性

7

对于Clojure中的map和record之间的相等性,我感到困惑。在第一个示例中,我们有两种不同类型的结构相等。相等性函数=返回true:

user> (defn make-one-map
         []
       {:a "a" :b "b"})
#'user/make-one-map
user> (def m1 (make-one-map))
#'user/m1
user> m1
{:a "a", :b "b"}
user> (def m2 {:a "a" :b "b"})
#'user/m2
user> m2
{:a "a", :b "b"}
user> (= m1 m2)
true
user> (type m1)
clojure.lang.PersistentArrayMap
user> (type m2)
clojure.lang.PersistentHashMap

在第二个示例中,我们有一个哈希映射和一条记录,它们在结构上是相同的,但“=”函数返回false:
user> (defrecord Titi [a b])
user.Titi
user> (def titi (Titi. 1 2))
#'user/titi
user> titi
#user.Titi{:a 1, :b 2}
user> (= titi {:a 1 :b 2})
false

为什么会有这些差异?我正在使用Clojure 1.3版本,发现它们真的很令人困惑。
2个回答

17

defrecord的文档字符串中可以看到:

此外,defrecord会定义基于类型和值的=,并会定义与java.util.Map契约一致的Java .hashCode和.equals。

因此,在使用=时,会考虑类型。您也可以使用.equals代替:

user> (.equals titi {:a 1 :b 2})
true

为什么PersistentArrayMap和PersistentHashMap的实例在使用=运算符比较时相等,但是类型函数表明它们不是同一种类型? - z1naOK9nu8iY5A
7
"类型和值基础相等"的承诺在defrecord的文档字符串中说明,适用于记录。另一方面,普通地图应该参与价值为基础的=方案,并且它们确实参与其中,以至于(=(hash-map:foo 1:bar 2)(sorted-map:foo 1:bar 2))(=(java.util.HashMap.{:foo 1:bar 2}){:foo 1:bar 2})都是true - Michał Marczyk

8

PersistentArrayMapPersistentHashMap 从概念上讲是相同的,因为当 ArrayMap 不断增长时,由于性能原因,它会自动转换为 HashMap。用户级别的代码通常不需要区分这两者。

defrecord 数据类型则不同于其他 map 类型。它是一种独立的类型,可能实现完全不同的接口,并且不应被某种其他形式的 map 自动替换。它在概念上与普通 map 不相等,因此 = 返回 false。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接