There are two ways to implement a protocol for any given type:

Provide implementations for protocol methods when a type is initially defined via

`deftype`

or`defrecord`

; this is called*inline implementation*.Use the

`extend*`

functions to register implementations for a type with the protocol.

Let’s contrast the two approaches in Examples 6-3
and 6-4 through implementing the
`Matrix`

protocol for the `Point`

record
type, where we’ll consider a point to be a 2×1 matrix:

Example 6-3. Implementing a protocol inline

(defrecord Point [x y] Matrix (lookup [pt i j] (when (zero? j) (case i 0 x 1 y))) (update [pt i j value] (if (zero? j) (condp = i 0 (Point. value y) 1 (Point. x value)) pt)) (rows [pt] [[x] [y]]) (cols [pt] [[x y]]) (dims [pt] [2 1]))

Example 6-4. Extending a protocol to an already-defined type

(defrecord Point [x y]) (extend-protocol Matrix Point (lookup [pt i j] (when (zero? j) (case i 0 (:x pt) 1 (:y pt)))) (update [pt i j value] (if (zero? j) (condp = i 0 (Point. value (:y pt)) 1 (Point. (:x pt) value)) pt)) (rows [pt] [[(:x pt)] [(:y pt)]]) (cols [pt] [[(:x pt) (:y pt)]]) (dims [pt] [2 1]))

A minor difference between the two approaches is how you access
field values: when you extend a type externally you have to access the
types’ fields using keywords (or interop forms like `(.x pt)`

), while when you provide inline
implementations, you can directly refer to field values by their name
since they are in the lexical scope.

Beyond that, the differences between inline ...

Start Free Trial

No credit card required