Putting things together
The simplest of the core protocols is Composition
Before digging into the semantics of this, a few things need to be explained.
- The
defprotocol
expression is very similar to Clojure's. - Protocol functions must be fixed arity. Though there can be multiple arities specified for them.
- Multiple arity and variadic function definitions are defined the same as they are in Clojure.
Tackling the two protocol functions first, comp*
defines how to combine, or compose, two or more values to produce a new value. x
is the value that determines which implementation of comp*
is called. Technically, xs
can be a list of values of any type. But the implementation must handle all the values in xs
. This is a place where a good type system will come in handy. In the future, I intend to allow you to add assert
statements to the implementations of protocol functions that will describe the conditions the arguments must satisfy. Those conditions will then be used at compile time to catch problems. But for now, just be careful. :)
In Clojure, the comp
function is used only for function composition. In Toccata, it serves that purpose as well, but also allows the composition of any other data type that implements comp*
. So list (or vector) concatenation, string concatenation, hash-map merging and set union, are all done using comp
.
Zero
Some data types that implement comp*
my have a particular value that when composed with other values of that type, do not effect the result. The empty list and empty hash-map are some examples. If that is the case, these data types should implement the zero
protocol function. When called with a value of that type, it should return the 'zero' value of that type. The presence of such an implementation has some interesting implications that we'll come to in future posts.
comp
Finally, the comp
function itself is just a plain function that allows the composition API to be variadic. Nothing special about it. The 1 argument arity is just there as an optimization. comp*
should still check to make sure that xs
has values in it. There is an implementation issue to be aware of. When the compiler sees a call site like
It produces the AST for
This should be purely an optimization that is invisible.
And finally
Many of you are probably saying "That's just a monoid" and you're exactly right. :)