Why is there a difference in return types of assoc
and dissoc
in Clojure, when their argument is a record? I mean that assoc
'ing a non-existent key still returns a record, but dissoc
'ing an existing key returns a map.
But, in a sense, both should produce either a map or a record, but not exhibit different behavior. What is the reason for this dissimilarity?
Record will be converted to an ordinary clojure map only if you'll dissoc
one of its predefined fields. It's very reasonable behavior, because records can't have undefined fields.
Consider the following code:
(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}
As you can see, both assoc
and dissoc
return a record as long as it satisfies Point
definition.
Record instances are guaranteed to include all the fields declared in the record definition.
When a declared field is removed from an instance, this guarantee would be violated. Hence a map is returned.
Apparently they are not guaranteed to exclude all fields not declared in the record definition, thus new fields can be added to instances.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With