Create two records Doctor
and Mr
that implement three methods:
(title this)
- Returns the title of the person (e.g. "Dr. Jekyll"
or "Mr Hyde"
)
(greet this greeting)
- Return personal greeting (e.g. "Hello Dr. Jekyll"
)
(rename this new-name)
- Change the name of a person
Guidelines:
Test your code with the unit tests on next slide
Define a protocol for each method
Let Doctor
and Mr
give different names to their arguments
Implement some of the record methods inside the record.
Implement some of the record methods outside the record (with extend-type
).
When you test your code, explore the different ways to instantiate a record
π Try to avoid implementing twice the exact same code (e.g. greet
)
(assert (= (title (Doctor. "Jekyll"))
"Dr. Jekyll"))
(assert (= (title (Mr. "Hyde"))
"Mr. Hyde"))
(assert (= (greet (map->Doctor {:name "Jekyll"}) "Hello")
"Hello Dr. Jekyll"))
(assert (= (greet (map->Mr. {:my-name "Hyde"}) "Hello")
"Hello Mr. Hyde"))
[source.eval-clojure, clojure]
(assert (= (title (rename (Doctor. "Jekyll") "Manhattan"))
"Dr. Manhattan"))
(assert (= (title (rename (Mr. "Hyde") "T"))
"Mr. T"))
(comment
(defprotocol IWithTitle
(title [this]))
(defprotocol IGreet
(greet [this greeting]))
(defprotocol IRenamable
(rename [this new-name]))
(defn default-greet [person greeting]
(str greeting " " (title person)))
(defrecord Doctor [name]
IWithTitle
(title [doctor] (str "Dr. " name))
IGreet
(greet [doctor greeting] (default-greet doctor greeting))
IRenamable
(rename [doctor new-name] (assoc doctor :name new-name)))
(defrecord Mr [my-name]
IWithTitle
(title [this] (str "Mr. " my-name))
IGreet
(greet [doctor greeting] (default-greet doctor greeting)))
(extend-type Mr
IRenamable
(rename [doctor new-name] (assoc doctor :my-name new-name)))
)
β No inheritance
β Defer implementation to a function that could be shared between records
β Records are immutable.
β It is better to have small protocols
β Usually, the name of a protocol starts with a I
β Inside a protocol, the object is named this
while inside a records it is named specifically.
β Usually records are defined in separate namespaces
β When to use records instead of maps?
β Records can be extended from the outside
β A protocol is an aggregation of function signatures
β Various ways to instantiate a record