Meikel Brandmeyer wrote a post on dispatch in Clojure with the URL title Static vs Dynamic. He writes:
Protocols are not the only place where we have a trade-off of static vs. dynamic. There are several places where such a trade-off can be spotted.
He provides the following example of static dispatch in a protocol:
(defprotocol Flipable
(flip [thing]))
(defrecord Left [x])
(defrecord Right [x])
(extend-protocol Flipable
Left
(flip [this] (Right. (:x this)))
Right
(flip [this] (Left. (:x this))))
Now it is true that each record maps to a 'class' on the JVM that is compiled. If you try and dispatch on anything other than Left
or Right
, you'll get a java.lang.IllegalArgumentException
with No implementation of method:...found for class:...
.
I ask because my understanding is that under the covers Clojure is effectively using the same JVM technology for polymorphic dispatch. We could rewrite the above as:
interface Flippable {
Flippable flip();
}
class Left implements Flippable {
Right flip();
}
class Right implements Flippable {
Left flip();
}
class Demo {
public static void main(String args[]) {
Flippable flippable = new Right();
System.out.println(flippable.flip);
}
}
Now whilst the types are compiled and statically checked, the actual dispatch is at runtime.
My question is: Is it accurate to describe dispatch in Clojure using a Protocol as 'static'? (assuming you're not using a map for dispatch but are relying on a record or type that corresponds to a class).