Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assoc and dissoc on Clojure records

Tags:

clojure

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?

like image 514
siphiuel Avatar asked Jul 03 '15 15:07

siphiuel


2 Answers

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.

like image 77
Leonid Beschastny Avatar answered Oct 18 '22 06:10

Leonid Beschastny


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.

like image 32
Leon Grapenthin Avatar answered Oct 18 '22 04:10

Leon Grapenthin