Putting things together
The simplest of the core protocols is
Before digging into the semantics of this, a few things need to be explained.
defprotocolexpression 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
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 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.
Many of you are probably saying "That's just a monoid" and you're exactly right. :)