Our first implementation of this protocol will be a very naive one for vectors of vectors. “Vector of vectors” is not a type in Clojure or even in the JVM, so we are simply going to extend the protocol to Clojure vectors:
(extend-protocol Matrix clojure.lang.IPersistentVector (lookup [vov i j] (get-in vov [i j])) (update [vov i j value] (assoc-in vov [i j] value)) (rows [vov] (seq vov)) (cols [vov] (apply map vector vov)) (dims [vov] [(count vov) (count (first vov))]))
Let’s stop and detail
extend-protocol. The first argument is the name of the protocol (
Matrix here). Then we have an alternation of
symbols (denoting type names like
IPersistentVector, the foundational vector
interface in Clojure) and lists (method implementations for the previously
specified type and extended protocol).
Method implementations are no different from regular functions.
Unlike in Ruby or Java, there is no implicit
the privileged first argument that determines which implementation of a
protocol to dispatch to is explicitly passed as the first argument to the
method. In this regard, protocol implementation functions are similar to
methods in Python.
A noteworthy aspect of protocols is that you are not required to implement all methods: Clojure will simply throw an exception if you try to call an unimplemented method.
extend-protocol is not the only
way to extend a protocol to a type; also available are:
We will talk about ...