关联和解散Clojure记录

sip*_*uel 11 clojure

为什么会出现在返回类型的差异assocdissocClojure中的,当他们的说法是一个记录?我的意思是assoc"不存在的键仍然会返回一条记录,但是dissoc现有的键会返回一张地图.

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

Leo*_*tny 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}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,assoc并且dissoc只要它满足返回一个记录Point的定义.


Leo*_*hin 7

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

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

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