1- Protocols

As define in the documentation,

A protocol is a named set of named methods and their signatures, defined using defprotocol.

(defprotocol IFoo
  "IFoo doc"
  (fooA [this] "fooA doc")
  (fooB [this] [this a] "fooB doc"))

You can add some documentation to the protocol and to each methods it contains. You don’t need to provide methods’ implemantation. After created your protocol, you can use deftype, defrecord or reify for defining its methods implementation.

In our case, we will use deftype because the major difference between deftype and defrecord is that deftype provides just the functionalities implemented by the user, contrary to defmethod that implements a lot of things that will not here to help us to understand the generated javascript code.

Let’s see the below example:

Now try to understand how the clojurescript compiler generates a basic protocol in javascript. Use KLIPSE to see the generated javascript code:

OK! If you are like me, you give me that the generated code is difficult to understand! So, let’s simplify it:

/**
 * Protocol Fly receive a javascript object
 * if the object implement fly => call fly
 * else throw exception
 */
fly = function(this$) {
    if(this$._Fly$fly != null) {
        return this$._Fly$fly();
    } else {
        throw "fly not supported!";
    }
};

/**
 * Type Bird that implement fly function
 */
Bird = function() {};
Bird.prototype._Fly$fly = function() {
    return "Bird uses natural wings.";
};

/**
 * Type Plane that implement fly function
 */
Plane = function() {};
Plane.prototype._Fly$fly = function() {
    return "Plane uses metal wings.";
};

/**
 * Type Empty that not implement fly function
 */
Empty = function() {};

/**
 * Call Fly.fly for each type you build
 */
a380 = new Plane();
eagle = new Bird();
none = new Empty();
console.log(fly.call(null, a380)); 
console.log(fly.call(null, eagle));
console.log(fly.call(null, none));

I hope now it’s more clear, when you define a protocol, you define a set of functions. Each function receive a javascript object, checks if this object implements a specific function, if that is the case this function launch the specific function. That’s all!