Some results from the Ioke experiment


It’s been a bit over 18 months since I first released Ioke in the wild. During this time I’ve always been specific about Ioke first and foremost being a language experiment. I changed many things to see what would work and what would not. I thought I’d take stock and take a look at a few of these decisions and how I feel about them now. Ioke never got a huge user base, of course, so most of these impressions are based on my continued working on the language, and also experiences trying to explain features of the language.

This does not mean in any way that the Ioke experiment is over. I will continue working on Ioke and see what else interesting will come out of it.

White space separation for method calls

I adapted Io’s, Self’s and Smalltalk’s syntax for Ioke. This meant I could use periods to end expressions instead (taking the role of semicolons in most other languages). Personally I like this a lot. Readability really improves substantially by using white space for method calls. The only thing that makes it a bit tricky is the interaction regular expression syntax. I ended up adding an initial character to regular expressions to make them easily distinguishable. I thought I would dislike that more than I do. So white space is definitely a win.

Keyword syntax in method calls

Having methods take keyword arguments and positional arguments baked in to the language was also a big win. It’s really a huge difference between this approach and something like Ruby – having it first class means it is easy to do things like collecting all keyword arguments, provide default values and so on. It also makes introspection and documentation much better. Finally, the duality if dictionary creation with keywords and regular method invocation ended up being very pleasing. Another clear win. Languages should have keyword arguments.

Nontraditional naming

I wanted to see what would happen if I stayed away from the traditional names in the object oriented languages of today. So I didn’t use Object, String, prototype, slot, clone or property. The most obvious place for this is in the core concepts of the language. The place where user code starts is called Origin. I’m don’t miss Object as such, but I’m not sure Origin is the clearest way of talking about this object. My current thoughts are going in the direction of something like “Vanilla” (from Flavors), or “Something”.  Another problematic renaming was to talk about the act of creating a new object as “mimicking”, and call the parents of an object “mimics”. It ended up being very confusing, both from a verb/noun standpoint, but also just from simply being to opaque. So that’s a definite failure. I’m still comfortable with “cell” instead of “slot” or “property”. I’m also happy with “Ground”, “Base” and “DefaultBehavior”. All of these communicate clearly what they should. I’m also happy about the renaming of “String” to “Text”. I don’t use the type name much in Ioke code, but when I do “Text” feels much better.

Numerical tower, and no real numbers

I’ve always liked numerical towers in programming languages, and it feels good to have it in Ioke. Ratios are also necessary as first class concepts. I also decided to not have real numbers, only the equivalent of BigDecimals. That was probably a good decision for Ioke, and I still feel real numbers are problematic. I don’t think removing them from the language is the right solution though.

Condition system instead of exceptions

The decision to adapt and include a condition system based on Common Lisp was definitely a success. I like the programming model and it makes code much more flexible and expressive. Clear win.

No global scope

This is also a clear win. It’s a tricky one in many languages do. You have to unify things to a high level to make it possible to get away from global state. But I think the benefits way outweigh the cost of this.

Specialized forms of code

Ioke have quite a few variations in runnable code. The main distinction is between things that are lexically scoped and things that are object scoped. Methods, Macros and Syntax are object scoped, while Blocks and Lecros are lexically scoped. This seemed like a good idea at the time, but if I were to do it again, I would try to unify several of those – at the cost of making the evaluation rules slightly more complicated. Especially having methods that aren’t lexical closures still surprises me regularily. I wonder if I was influenced by the way Ruby works when designing these parts.

Prototype OO

I’ve always maintained that properly implemented propotype based object orientation is both conceptually simpler and more powerful than class based object orientation. I still believe this to be true, and I still think prototype based is better than class based. However, there are some places where the model breaks down. There are some situations where it just makes sense to have a class that describes objects. Take numbers for example. In a prototype based scheme, what is the parent of the number 2? Is the parent the number 1? Not really. In Ioke I added a singleton object Number that is the parent of all numbers. But that still becomes weird since you could write code like “Number + 9″, and expect that to work. I’m not sure how to solve this problem. Of course, prototypes can represent classes without problem, but my problem is mostly what makes sense intuitively.

Ruby-like load/require system

For a language with a global scope and/or total mutability, it works quite well to just have things represented as scripts that will modify a shared environment when loaded. However, there are things that become cumbersome – parameterization of modules/files become very ad hoc, and there is a real risk of conflicting names. If I were to redo this part I would probably opt for something slightly less convenient but more powerful, that allow you to work with software modules in a better way. Exporting parts and keeping other parts private, parameterize modules, bind modules under different names, and so on.



Ioke at Chicago and Iowa Code Camp


This saturday, May 1st, I will be talking at both the Chicago Code Camp and the Iowa Code Camp. I will be giving an introduction to Ioke at both code camps, and I will actually have slightly more time than I usually do – so hopefully this introduction will be the best intro to Ioke ever. I’ve also hacked on some fun stuff for Ioke lately that hopefully will be done by Saturday, so I might show some of that.

Hope to see many of you there!



Ioke P released


I am very happy to announce that Ioke P has finally been released!

Ioke is a language that is designed to be as expressive as possible. It is a dynamic language targeted at the Java Virtual Machine. There also exists a version for the CLR. It’s been designed from scratch to be a highly flexible general purpose language. It is a prototype-based programming language that is inspired by Io, Smalltalk, Lisp and Ruby.

Homepage: http://ioke.org
Download: http://ioke.org/download.html
Programming guide: http://ioke.org/wiki/index.php/Guide
Wiki: http://ioke.org/wiki

The two specific releases that encompass Ioke P are ikj 0.4.0 and ikc 0.4.0.

Ioke P is the fourth release of Ioke. It includes many new features compared to Ioke E:

  • Number Infinity
  • eval
  • Reflector
  • Hooks
  • First class Runtime
  • New parser
  • Tuples
  • Structs
  • Destructuring assignment
  • Message rewriting
  • Functional composition
  • Sequences
  • Dictionary and Set versions of Enumerable methods
  • Enumerable group, Enumerable groupBy
  • Set operations for union, intersection, membership, subset and superset testing
  • ISpec stubbing and mocking
  • IIk history
  • DokGen on separate projects

Ioke P also includes a large amount of bug fixes.

Features:

  • Expressiveness first
  • Strong, dynamic typing
  • Prototype based object orientation
  • Homoiconic language
  • Simple syntax
  • Powerful macro facilities
  • Condition system
  • Aspects
  • Java integration
  • Developed using TDD
  • Documentation system that combines documentation with specs
  • Runs on both the JVM and the CLR

The many things added in Ioke P could not have been done without the support of all the Ioke contributors. Thank you!

Regards
Ola Bini    – ola.bini@gmail.com



Ioke sequence support


The last two weeks I’ve been working on adding external iterators to Ioke. This work is now done and merged, so I thought I’d just describe it a bit.

But first, why do I need explicit iterators in Ioke? Ruby has gotten by without them for a long time, only implementing a Generator library using continuations, in the standard library. It’s pretty nice, since you don’t really need to do anything explicit to get external iterators from internal ones. Of course, the problem is that it’s very inefficient to implement them like this. So I decided that Ioke should have an explicit protocol for external iterators. You can implement internal iterators using external ones efficiently, but not the other way around.

The two major objects for this in Ioke is called Sequence and Mixins Sequenced. Sequenced is the mixin that gives you access to several helper methods if you implement the “seq” method. If you implement “seq” and mixin Sequenced you will also get an “each” method and Enumerable. The “seq” method is expected to return something that mimics Sequence and has one “next” method, and one “next?” method. That’s all. The “next?” method returns true if there is another element in the sequence, and “next” returns the next one. The protocol is undefined if you call “next” when “next?” would have returned false.

Sequenced give you an “each” method that in addition to the regular each-protocol will also return the result of calling “seq” if you don’t give any arguments to “each”.

Except for that, you will get several methods that just call “seq” and calls the same method on the result of that. These methods are: “mapped”, “collected”, “filtered”, “selected”, “grepped”, “zipped”, “dropped”, “droppedWhile” and “rejected”. These methods are also the same as exist on Sequence. These methods return new sequences that implement the same behavior as the methods with similar names on Enumerable.

Finally, Sequence also mimics Mixin Enumerable. Once you call one of the Enumerable-methods, the whole sequence will be realized, or as much as is necessary to give an answer. A small example of how you could use it:

(1..100000000) mapped(x, x*x) filtered(x, x % 3 == 0) takeWhile( < 10000 )

This example creates a range from 1 to 100,000,000 and finds all the squares that are less than 10,000 an d that is evenly dividable by 3.



A new parser for Ioke


Last week I finally bit the bullet and rewrote the Ioke parser. I’m pretty happy about the end result actually, but it does involve moving away from Antlr’s as a parser generator. In fact, the new parser is handwritten – and as such goes against my general opinion to generate everything possible. I would like to quickly take a look at the reasons for doing this and also what the new parser will give Ioke.

For reference, the way the parser used to work was that the Antlr generated lexer and parser gave the Ioke runtime an Antlr Tree structure. This tree structure was then walked and transformed into chained Message’s, which is the AST that Ioke uses internally. Several other things were also done at this stage, including separating message chains on comma-borders. Most significantly the processing to put together interpolated strings and regular expressions happened at this stage. Sadly, the code to handle all that was complex, ugly, slow and frail. After this stage, operator shuffling happened. That part is still the same.

There were several problems I wanted to solve, but the main one was the ugliness of the algorithm. It wasn’t clear from the parser how an interpolated expression mapped into the AST, and the generated code added several complications that frankly weren’t necessary.

Ioke is a language with an extremely simple base syntax. It is only slightly more complicated than the typical Lisp parser, and there is almost no parser-level productions needed. So the new parser does away with the lexer/parser distinction and does everything in one pass. There is no need for lookahead at the token level, so this turns out to be a clear win. The code is actually much simpler now, and the Message AST is created inline in the new parser. When it comes to interpolation, instead of the semantic predicates and global stacks I had to use in the Antlr parser, I just do the obvious recursive interpolation. The code is simple to understand and quite efficient too.

At the end of the day, I did expect to see some performance improvements too. They turned out to be substantial. Parsing is about 2.5 times faster, and startup speed has improved by about 30%. The distribution size will be substantially smaller since I don’t need to ship the Antlr runtime libraries. And building the project is also much faster.

But the real gain is actually in maintainability of the code. It will be much easier for me to extend the parser now. I can do nice things to make the syntax more open ended and more powerful in ways that would be very inconvenient in Antlr. The error messages are much better since I have control over all the error states. In fact, there are only 13 distinct error messages in the new parser, and they are all very clear on what has gone wrong – I never did the work in the old parser to support that, but I get that almost for free in the new one.

Another thing I’ve been considering is to add reader macros to Ioke – and that would also have been quite painful with the Antlr parser generator. So all in all I’m very happy about the new parser, and I think it will definitely make it easier for the project going forward.

This blog post is in no way saying that Antlr is bad in any way. I like Antlr a lot – it’s a great tool. But it just wasn’t the right tool for Ioke’s syntax.



Continuous Integration for Ioke with Cruise


I’ve felt the need for this since I put out the CLR version of Ioke, and now I’ve finally managed to make it happen. Even though I’m the only person with commit rights to Ioke so far, it is still good to have continuous integration running, especially since there are at least seven different builds I want to test, 3 on linux and 4 on windows.

I now have two servers running this. They are not public right now – I will post something when the dashboard is up – but the CI server will send notification emails to the ioke-language Google Group with status.

The current setup tests Java 1.5, Java 1.6 on Linux and Windows. It tests Mono on Linux and Windows, and .NET on Windows.

As a CI server I’m using Cruise, ThoughtWorks own Continuous Integration server. Cruise is a commercial product, but open source projects can use it for free. I’m very happy about it from earlier projects, which is why I decided to use it for Ioke.

ThoughtWorks also gave me two virtual machines to run this CI server – which I’m very grateful for.



Videos from the Chicago ACM Ioke talk


This Wednesday I gave a talk about Ioke at the Chicago ACM. This was actually great fun and I’m fairly happy with the presentation. This is without doubt the best quality Ioke presentation available so far.

You can see it here: http://blip.tv/file/2229441

And here: http://blip.tv/file/2229292



The Ioke philosophy


I have in various circumstances used a list of statements, a kind of Ioke manifesto, that tries to give the spirit of what kind of guidelines I use when designing Ioke. Some of them are very serious, and some … well, more in jest. I thought I’d expand on them a bit there. In the tradition of these kind of manifestos, Ioke values the thing on the right, but values the thing on the left much more.

Oh, and remember that these ideas… They are really my ideas and thoughts and values. Nothing else. It is not in any way objective. So please don’t take offense, get riled up or start any holy wars.

Expressiveness over performance

This is really the full manifesto of Ioke, if you ever had to choose just one. In any situation where I have to choose between expressiveness or performance, expressiveness is always the answer. The side effect is of course that Ioke is not a fast language at all. But I believe it is one of the most expressive you can find – at least if you measure expressiveness the way I do.

Abstraction over low level interfaces

A special case of expressiveness is abstraction. When I get drunk and rant about programming languages (something that happens all too often) one of the words I use all the time is “abstraction”. As it turns out, being able to abstract things – no matter what they are – is one of the most important things in a programming language – for me. The ability to abstract objects and classes of objects is one of those. The ability to abstract functionality is another. The ability to abstract structure is a third. The ability to abstract syntax is a fourth. The ability to abstract programming substrate is another. The ability to abstract paradigm is another. And so on. Abstraction is really the possibility of making completely different things work together. It is also the possibility of making things communicate, no matter what they are. If you can abstract on any dimension, this means that you can make your code communicate to any stakeholder. And that is important.

In fact, it is important enough that I’m considering adding another point, such as “Communication over implementation”. Should I?

Higher order functionality over explicitness

The higher you get on the order of things, the more declarative you can be. And the more declarative you can be, the easier it is to communicate intent. The disadvantage is of course that it is hard to judge the implementation behavior of something if you only communicate the intent of code – but I find that argument is false. If the intent is correctly specified, it should be possible to actually have the correct implementation behavior, no matter what.

First class over implicit functionality

My ThoughtWorks colleague Bradford Cross talks about First class oriented programming, and has written many blog entries where this shines through. I totally agree with him. The more things you can make first class in your language, the better. Because those things that aren’t… Well, they will be the conceptual walls of your language. That’s really all there is to it. So making as many things as possible first class will actually expand the borders of your nation. Ehm. Language, that is.

“Right is better” over “Worse is better”

OK, this I couldn’t avoid doing. I like Gabriel’s essay. I just thing that the concept is abhorrent. I guess I’m of the mindset that can’t accept that bad things can thrive. I mean, from a logical standpoint I understand how it works. I just don’t want to be part of it. But from another level, actually releasing something half finished plays into Worse is better. So I’m not sure about this one. I just feel that the right solution is really better than the quick and dirty one.

Language oriented programming over APIs

What does Language Oriented Programming really mean? I’m not sure I can give you a canonical definition, but in my mind it goes back to the tradition of “little languages” in Lisp – which means you mold your environment into the perfect environment for solving your problem. And then you solve your problem in that environment.

I also believe that polyglot programming and external DSLs are an important piece of this puzzle. So all in all, the features in Ioke that enable LOP is the ease of creating internal and external DSLs, and the interoperability of both the JVM and the CLR. These things together make it easier to solve problems in a language oriented fashion.

“Code as data” over “Data as code”

The more I think about this one, the less sense it makes. What I wanted to express was the point of view that data and code aren’t really two different things, and that Ioke should treat them more or less the same – much like the Lisp tradition of symbolic expressions. In Ioke this is realized by having the AST being first class and core to the execution of any code. This AST can be modified in any way, created from scratch and so on, meaning that code and data get blurred together. There is also another discussion under the covers here, dealing with smart and dumb data. What is “code as data”? Does it deal with smart or dumb data? I don’t know.

Homoiconicity over syntax

Ioke plays a lot of cards surrounding homoiconicity – meaning that the structures used to represent code are the same as what you use to code. This allow easy access to lazy evaluation and syntactic macros, and is thus extremely powerful. This is one of the core parts of the expressiveness of Ioke, and it is more important than useful syntax. Which means that when the balance of syntax vs homoiconicity gets skewed, it will be syntax that pays the price.

Syntax over explicit APIs

But if you have actually looked at Ioke, you know that Ioke likes syntax. It doesn’t like it as much as Ruby or Perl, but it likes it much more than Dylan or Lisp. But in the same way Dylan works, Ioke syntax is generally canonical and maps very cleanly down to the message sending paradigm. This makes the AST clean and regular, without having to care about different syntax elements. Take assignment. Doing something like “foo = 42″ will end up with the AST “=(foo, internal:createNumber(42))”. Here, “=” is clearly defined as just a simple message send, just as anything else. And in the same manner, the creation of a literal (the number 42) is also represented as a message send. The AST in Ioke is very regular and simple. It has exactly one node type – the message.

So saying syntax over explicit APIs means that the Ioke way of creating a new list is to use the [] method, not the list method. Because it reads better. I find that judicious syntax make the intent of my code better. The right amount of syntax makes my code more readable, not less. This can be abused, but frankly – I am not in the business of stopping people from doing stupid things. The good thing about doing stupid things is that it tends to remove the person doing it from being productive, sooner or later. It is a self balancing equation.



The Ioke object hierarchy


When designing the core Ioke libraries, I’ve tried to factor things out into different places, as much as possible. This have given rise to a pretty complicated object hierarchy, so I thought I’d describe it a bit closer here. This should make it a bit easier to understand how lookup of methods work, and where you should add functionality for the right effect. In this blog post I will go through most of the kinds in Ioke, notice how they fit together and also what kind of methods they contain.

OK, so let us start at the top. Even here we run into a small problem, of course – since Ioke is not single inheritance. One object can mimic more than one object, or none. There is no absolute requirement that everything is part of the same inheritance chain. We will get back to this in a while, but at first we can ignore that, and imagine that the hierarchy is simple.

At the top of the Ioke hierarchy is the object called Base. This object has no mimics, and contains only the most essential methods. These are methods that allow the introspection and modification of cells, such as “cell”, “cell=”, “cell?”, “cellNames”, “cells” and so on. It also includes “documentation” and “documentation=”. It includes the assignment method “=”. And finally it contains “mimic” that allow you to create new instances. This method is basically the only way of allocating new objects in Ioke, which means it is pretty important. If you need the functionality but without mimicking Base, you can either copy the method itself, or mimic BaseBehavior (we’ll get back to this in a minute.)

OK, so Base is the absolute base of everything in Ioke. But Base is not the equivalent of the Object found in most other languages – in most cases you won’t get the expected behavior if you mimic directly from Base. The object that is supposed to be used as the origin of new objects is called Origin. But before we go there, we need to talk about Ground.

Ioke actually overloads the term ground to mean two slightly different things. First, there is an object called Ground, and secondly, the ground of an evaluation is basically the default context. The default ground at the top level is the object Ground. Now, Origin mimics Ground. This means that if you add something to the top level, that will be in the inheritance chain of all objects. This is the closest you will get to a global scope in Ioke.

The Ground object mimics different things depending on which implementation you are running. If you’re on ikj, Ground will mimic both IokeGround and JavaGround, where JavaGround is the object where all Java integration machinery resides. On ikc, Ground currently only mimics IokeGround, but I expect to add CLRGround sooner or later. IokeGround is the place where all so called global names in the system is defined. This is where you find the cells for “Text”, “Symbol”, “Number”, “Range” and also “false”, “true” and “nil”. Yes, that is right, these names are not constants – they are just cells on IokeGround.

IokeGround mimics Base – so that is where the connection to the base of the hierarchy actually is made. But IokeGround also mimics and object called DefaultBehavior. As the name implies, this is where most of the Ioke behavior resides. DefaultBehavior in itself is basically a mixin, only providing these methods. You should not mimic DefaultBehavior in itself, if possible.

(Incidentally, that is the difference between an object that is supposed to be a mixin, and a regular object. In Ioke there is no real difference at the structure level – it is only about intent.)

DefaultBehavior doesn’t contain many methods in itself, but instead mixes in several more focused objects, such as “DefaultBehavior Aspects”, “DefaultBehavior Assignment”, “DefaultBehavior Boolean”, “DefaultBehavior Case”, “DefaultBehavior Conditions”, “DefaultBehavior Definitions”, “DefaultBehavior FlowControl”, “DefaultBehavior Internal”, “DefaultBehavior Literals” and “DefaultBehavior Reflection”.

If you want to make the intent of a mixin very clear, you mimic the Mixins object. This object include the bare necessary things to add new cells and introspect on them. “Mixins Comparing” and “Mixins Enumerable” are two examples of such mixins.

And that is basically the full story. Any other object you will find in the system is almost certainly derived from Origin, and the hierarchy under Origin is pretty shallow and flat, at least for now. I’ve considered making the intent of different collections a bit more specific, in the manner of Smalltalk – but this hasn’t happened yet.



Message chains and quoting in Ioke


One of the more advanced features in Ioke is the ability to work with first class messages. At the end of the day, you are manipulating the AST directly by doing this, which means that you can do pretty much anything you want. The manipulation of message chains is the main way of working with macros in Ioke, so understanding what you can do with them is pretty important.

The documentation surrounding these pieces is spread all over the place, so I thought I’d take a look at messages and the way you construct and modify them.

Messages

The first step in working with message chains is to actually understand the Message. Message is the core data structure in Ioke, and it has some native properties that define the full structure of the Ioke AST. There are four pieces of the structure that is central to messages, and a few more that is less interesting. So let us look at the core structure. It is actually extremely simple. These are the things that makes a Message:

  • Name – all messages have a name. From the perspective of Ioke, this is a symbol. It will never be nil, but it can be empty.
  • Arguments – a list of messages, zero or more.
  • Prev – a pointer to the previous message in the chain, or nil if there is no previous.
  • Next – a pointer to the next message in the chain, or nil if there is no next message.

A message can also wrap a value. In that case the message will always return that value, and no real evaluation will happen. This can be used to insert any kind of value into a message chain that will later be evaluated. This is called wrapping.

A message chain is just a collection of messages, linked through their Prev and Next pointers.

The arguments to a message are represented as a list of messages. This make sense if you think about it for a few seconds.

OK, now you know what the Ioke AST looks like. It isn’t harder than that. Now, if you actually want to start working with messages, there are several messages that Message can receive, that allow you to work with them. The simpler ones (that I won’t explain closer) is “name”, “name=”, “arguments”, “arguments=”, “next”, “next=”, “prev”, “prev=”.

There are a few more interesting ones that merit some explanation. First, “last”. This message will just return the last message in the message chain. It is the equivalent of following the next pointer until you come to the end.

It’s important to keep in mind that Message is a mutable structure, which means you need to be careful to not change things that will give you unexpected changes. For example, if someone sends in a message, you shouldn’t generally actually modify that without copying it. Now, if you only want to copy a message without copying recursively the next pointer, you can just mimic it. Otherwise you use the method “deepCopy” which will actually copy both the next pointer and the arguments recursively.

Now, if you want to add new arguments to a message, you can use “appendArgument”. This method is aliased as “<<”. It will also return the receiver, so you can add several arguments by linking calls to appendArgument/<<. If you want to add a message at the beginning of the argument list, you instead use >>.

One of the more annoying things is that once you set the next pointer, you generally need to make sure to set the previous pointer of the next value too, unless you are setting it to nil. The same thing is true when setting the prev pointer. So, in the cases when you want to link two messages, you shouldn’t set these specifically, but instead use the “->” method. This allow you to link two Ioke messages. For example “msg1 -> msg2″ will actually set the next pointer on msg1 and the prev pointer on msg2. If you do “msg1 -> nil” it will set the next pointer to nil.

And that’s basically it. If you need to actually evaluate the messages, you can either use “sendTo” or “evaluateOn”. The main difference here is that sendTo will actually not evaluate the message chain. It will only evaluate the message that is the receiver of the call. The evaluateOn method will follow the message chain and evaluate it fully, based on the context arguments given to it.

Oh, one last thing. To create new messages from scratch, there are a few different ways. First of all, you can wrap a value like this: “Message wrap(42)”. That will return a new message that wraps the number 42.

You can create a message chain from a piece of text by doing ‘Message fromText(“one two three”)’. This will return a message chain with three messages, linked together.

Finally, you can create a new message chain by using the from-method. You use it like this: “Message from(one two(three) four)”. What is returned is the message chain that is the argument. If you think about it for a few seconds, you can probably guess how to implement this using an Ioke macro.

Quoting

Now that we understand messages and message chains, let us take a look at how to create new chains in a flexible way.

First of all, all of the above methods are all very useful and nice, but they tend to be a bit verbose. Coming from a Lisp background I felt inclined to put the quoting characters to good use for this. So, first of all, the single quote (‘) does the same thing as “Message from”. The back quote (`) does the same thing as “Message wrap”. So, to wrap the number 42, you can just do `42. In this case you don’t need parenthesis, since the back quote is an operator. To create a new message chain, use the single quote: ‘(foo bar(x) baz).

We almost have everything we need, except that we need some convenient ways of actually putting things into these message chains without having to put them together by hand.

Say for example we have a variable “blah” that contains an unknown message. We want to create a message “one” that is followed by the message in the variable “blah”. And then finally we want to add two messages “bax” and “baz” after it. We could do it like this: x = ‘one. x -> blah. x last -> ‘(bax baz). All in all, that is not too bad, but we can do better. This is done using the splice-quote operator, which is just two single quotes after each other. Using that it would look like this: ”(one `blah bax baz). In this case, the back quote inside of the splice-quote call will actually be evaluated in the current context and then have the result be spliced into the message chain being created. Now, only use the back quote if you are sure you can modify it. If you want to copy blah before inserting it, use the single quote again, instead of the back quote: ”(one ‘blah bax baz)

All in all, this is really all you need, and you can take a look at the core libraries and see how they are used. A typical example is the comprehensions library, and also the destructuring macros. In general, creating these message chains on the fly is the most useful inside of syntax macros.

I am planning to add a new feature to Ioke, that allow you to do tree rewriting for manipulating chains in different ways. This will be a feature built on top of the primitives described here, and these features will continue to be the main way of working with message chains for a long time.