Third and final day with Io (as far as the book is concerned). This time Io metaprogramming abilities are used to bend the language into strange shapes.
Of course, metaprogramming bends the mind just as much at the language, and this last day is quite a ride.
Everything is up for redefinition, and new syntactic structure can be added as well. Operators were covered in Day 2. Today curly braces and square brackets are covered as well. The neat thing is that the method used for the iterpretation is looked up using the same logic as other methods. So it is possible to define a square bracket syntax to access list items simply with:
With the definition above, it becomes possible to use the familiar bracket syntax:
Updates are not possible (as far as I can tell), however, so for that usage it is less expressive than the
= methods in Ruby.
The content inside the braces or brackets must be a comma separated list, each element acting as an argument for the
squareBrackets methods (no link as I could not find any documentation for either method).
A moderately annoying problem with operator extensions is that they are not available in the file in which they are defined.
The last topic covered was concurrency. Io implements an actor model, like all the cool kids (Erlang, Scala, …). The book doesn’t go into details. And the available documentation is sparse as well. But from what I could gather, the model is cooperative concurrency, and an asynchronous message is a simple extension of the standard one, with one caveat: the
call sender information is lost when asynchronous messages are used. Or more precisely,
call sender does not return the original initiator of the call, but the piece of logic in the target coroutine that handles the dispatching of messages. So to return a answer, the sender must be passed as argument.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
The code above will spawn two agents, and they will exchange messages (5 times here).
Today’s exercises are only on metaprogramming, essentially syntax extension.
Indenting XML output
To indent properly, the Builder must keep track of the nesting depth. This is done with a slot, and a few utility methods. The
depth slot is the nesting depth, it is changed with
nest (increase) and
unnest (decrease), which should bracket the code that processes children. Finally,
indent emits the required amount of blank space.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
produces the following
1 2 3 4 5 6 7 8 9 10 11
Bracket syntax for list
This is not difficult: the implementation just creates an empty list, then
append each arguments to the list, before returning it:
1 2 3 4 5 6 7
The result is:
Attribute syntax for XML Builder
The last exercise is a bit tricky. The code as presented in the code mixes parsing and output. The problem now is that the first argument could be the attribute list, rather than a child element. The solution is to stop printing the result as we parse it, and instead to build a string representation of the XML.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
Once loaded, it can interpret the following (using
1 2 3 4 5 6 7 8 9 10 11
Wrapping day 3 and Io
The terseness and uniformity of syntax achieves quite a great deal; the actor model is modern and hip, although the cooperative concurrency isn’t.
This is a language that requires commitment; it is less clear it deserves so much.