Records, Types and reify
When to use what: plain maps for most data; records when you need protocol dispatch on a type with performance; deftype for low-level data structures; reify for one-off implementations.
;; defrecord: a map-like type with fields (works with all map functions)
(defrecord Person [name age])
(def ana (->Person "Ana" 30)) ; positional factory
(def bo (map->Person {:name "Bo" :age 25})); map factory
(:name ana) ; "Ana"
(assoc ana :email "a@x.com") ; still a Person, with an extra key
(dissoc ana :name) ; dissoc'ing a field returns a plain map
(instance? Person ana) ; true
(= ana (->Person "Ana" 30)) ; true (value equality)
(record? ana) ; true
;; deftype: a low-level type, no map behavior, supports mutable fields
(deftype Counter [^:volatile-mutable n]
clojure.lang.IDeref
(deref [_] n)
Object
(toString [_] (str "Counter(" n ")")))
(def ct (Counter. 5))
@ct ; 5
;; reify: an anonymous object implementing protocols/interfaces
(def greeter
(reify
Object
(toString [_] "I'm a greeter")
Describable
(describe [_] "greets people")))
(str greeter) ; "I'm a greeter"
;; proxy: subclass a Java class (when an abstract class is required)
(def task
…