Clojure记录的关联和解散

时间:2015-07-03 15:32:49

标签: clojure

为什么Clojure中assocdissoc的返回类型存在差异,当他们的参数是记录时?我的意思是assoc使用不存在的密钥仍会返回记录,但是dissoc现有密钥会返回一个地图。

但是,从某种意义上说,两者都应该产生地图或记录,但不会表现出不同的行为。这种不同的原因是什么?

2 个答案:

答案 0 :(得分:14)

只有当您dissoc其中一个预定义字段时,记录才会转换为普通的clojure地图。这是非常合理的行为,因为记录不能有未定义的字段。

请考虑以下代码:

(defrecord Point [x y])
(def p (Point. 1 2)) ; => Point{:x 1, :y 2}

(assoc p :x 3) ; => Point{:x 3, :y 2}
(dissoc p :x)  ; => {:y 2}

(assoc p :z 3) ; => Point{:x 1, :y 2, :z 3}
(dissoc p :z)  ; => Point{:x 1, :y 2}

(-> p
    (assoc :z 3) ; => Point{:x 1, :y 2, :z 3}
    (dissoc :z)) ; => Point{:x 1, :y 2}

如您所见,assocdissoc只要满足Point定义,就会返回记录。

答案 1 :(得分:7)

保证记录实例包含记录定义中声明的所有字段。

当从实例中删除声明的字段时,将违反此保证。因此返回一张地图。

显然,他们不能保证排除记录定义中未声明的所有字段,因此可以将新字段添加到实例中。