Blame it on Io! A slow-paced introduction to the Io language

Wednesday, March 15th, 2006

No posts in a week, I have been silent too long. Blame it on Io!

You see, Io is a contagious disease. It affects programmers’ brains. The incubation period is extremely short, due to the simplicity of its syntax. But the damages are extensive, particularly for Algol-derivative programmers: you will end up messed up! Huh… I forgot to mention the vectors include reading posts about Io. I just hope your infection will not be as bad as mine. (If I do not get google hits from E.R. fans with this paragraph, what will it take?)

Yo Io!

First things first, let’s get the token “Hello World!” implementation out of the way:

"Yo Io!" print

Aside from my poor taste in greeting phrases, you probably noticed how concise and simple this statement is. At first sight, to most programmers, it appears to be written backward. Not so if you think that the "Yo Io!" object — which happens to be a string — is being sent the message print. Everything in Io is an object, and I really mean everything: lists, files, strings, numbers and even messages!

Attack of the clones

Well that is not fully accurate, to be pedantic, I should have written: everything in Io is a prototype. Indeed, Io is a prototype-based language. C++/Java/C# programmers, here comes surprise #1: Io knows nothing about classes. In class-based languages, classes describes the structure and behaviour of objects in term of methods whereas instances hold the objects’ data. Prototype-based languages do not make this distinction. A prototype is both a class and an instance. To get a new instance, you clone an existing prototype. To get a new class you add or alter the behaviour of an existing prototype. Sounds complex? Let your inner mad scientist free:

Sheep := Object clone

In English, Sheep is defined as a clone of Object — the parent of all Io prototypes.

Sheep legCount := 4

In brain-damaged English, the legCount property of a Sheep is defined as four. Non-programmers would have you believe this is equivalent to: a sheep has four legs.

MutantSheep := Sheep clone

A MutantSheep is defined as a clone of a Sheep. No surprise here, we all knew that!

MutantSheep legCount = 7

But their legCount property is set to seven! Most inner mad scientists tend to go for six legs, but my inner mad scientist is also nonconformist. I explain the difference between = and := in the next section. Just pretend they are the same for the moment.

dolly := MutantSheep clone

Here be dolly the mutant sheep! The convention is to use an upper-case character at the beginning of the name of prototypes acting as classes and a lower-case character for prototypes acting as instances.

Lots of slots

Once again, I have to confess that I have been inaccurate: I wrote legCount was a property of a Sheep whereas, in Io speak, it is actually a slot of Sheep. A slot associates a value to a name within the context of a prototype. Sheep holds one slot named legCount with the value 4. Here comes surprise #2: slots can contain variables and methods.

Sheep baa := method("bah!" print)

The baa slot on Sheep is defined as a method which prints “bah!”. Simple, no?
You noticed earlier that Io has two different assignment operators: := and =. Both of them are actually methods on Object. := is actually parsed as setSlot and = is parsed as updateSlot. From the method names you probably inferred the difference: := creates a new slot on a prototype from a name and a value whereas = updates an existing slot with a new value.
Io interprets the previous code sample like this:

Sheep setSlot("baa", method("bah!" print))

There is madness to Io’s methods

In case you were wondering, method is a method on Object that creates anonymous methods. The self-referential aspect of what I just wrote surely enlightened you, not. Rewind. Slow motion. The method method takes a list of parameters. All but the last one are arguments to the created method. The last argument is the body of the method. In this example, I define the growMoreLegs slot on MutantSheep to be a method with one parameter:

MutantSheep growMoreLegs := method(n,
    legCount = legCount + n)

Apart from the slightly surprising syntax, I hope this all sounds pretty familiar so far. Things are about to change big time! Surprise #3: a method can control when and if to evaluate an argument. This lets us define flow control constructs (if, unless, while, etc.) as methods. Most of them already exist on Object of course. One construct is missing though and we will implement it here. But first, we will botch the job:

Object unless := method(cond, then, else,
    if(cond, else, then))

The problem: cond, then and else are evaluated when unless is called. We do not want that. What we want is: unless cond is true, evaluate then, otherwise evaluate else. In Io this is done like this:

Object unless := method(
    if(call eval argAt(0),
        call eval argAt(2),
        call eval argAt(1)))

Update: see jer’s comment for a better implementation
What looks like a nice trick, is actually extremely powerful. Lisp programmers laugh in the background, they’ve used it successfully since 1958! I will not explore this vast topic any further in this post — I must save some ammunition for future posts!
By the way, I hope you appreciated the fact that Io is a dynamic language: we just added a method to the Object prototype!

Lobby for Io!

Before concluding, I would like to point out that Sheep and MutantSheep are defined like slots. But what is the underlying prototype? In Io, this is the Lobby. So what? Well, Lobby ultimately derives from the Object prototype, like all other prototypes. But where do you think we found the Object prototype? Bingo! It is a slot in the Protos slot of Lobby. I suggest you read this again. You are not dreaming: Object is both a slot of a slot in the Lobby and an ancestor of the same Lobby. How is that for another self-referential bit of self-reference?

Time to conclude, I hope this introduction will entice you to dwell deeper into this really amazing language. Believe me, we have only scratched the surface!
For a more complete, formal and accurate presentation of Io, check out The Io Programming Language.
Visit the official website or join the posse on irc.freenode.net#io.

11 Responses to “Blame it on Io! A slow-paced introduction to the Io language”

  1. jer Says:

    You’re unless method could be better implemented simply like this:

    Object unless := method(
      if(call argAt(0) not, call argAt(1), call argAt(2))
    )
    

    This will allow you to use:

    unless(1 == 2, "stuff" println)
    

    or

    unless(1 == 2, "stuff" println, "otherstuff" println)
    

    Your current version requires all three arguments, and in Io, you can leave out any number of arguments if you desire (though not to confuse anyone, if you leave out an arg that a method/block needs, expect trouble).


  2. […] Back at Ozone’s you can find a crash introduction to Io, a relatively new prototype-based language. As explained in its official site: Io is a small, prototype-based programming language. The ideas in Io are mostly inspired by Smalltalk (all values are objects), Self (prototype-based), NewtonScript (differential inheritance), Act1 (actors and futures for concurrency), LISP (code is a runtime inspectable/modifiable tree) and Lua small, embeddable). […]

  3. ozone Says:

    Thanks jer for your comment (I hope you don’t mind, I modified the format slightly to improve readability). Your implementation is indeed more accurate.

  4. tejinder Says:

    hi, is Io any better/different from Ruby?

  5. ozone Says:

    Tejinder, Io is certainly different from Ruby. At the very least, Io is prototype-based whereas Ruby is class-based. The differences do not end there, far from it!
    On the better side of things, it is all a matter of taste. I would recommend learning (or having a good look at) both!

  6. Kevin Whitefoot Says:

    Apart from the prototype versus class distinction IO has futures, Ruby doesn’t (at least I don’t think so).

  7. Paulo Köch Says:

    Ruby vs. Io: I think it’s a matter of taste. They have somewhat different paradigms, so it’s like comparing two stripes of cheese. =P

    I already know ruby very well and I’m currently exploring Io. And liking it. =) Overall, it just seems more ‘pure’.

  8. fordston Says:

    Thankyou for your article!

    Is there a Smalltalk-like IDE for Io, and does this question even make sense?

    I.e., how does one keep track of all the protos and methods in the system? Is there a proto/method browser available?

    (I’m from Smalltalk, and, lately, from Java, — and only tenuously from either of them at that!).

    ford

  9. Alex Says:

    Have any Sheep or MutantSheep been harmed in the production of this article?


  10. I suspect that all the sheep (mutant or otherwise) would have been routinely destroyed.


  11. […] Blame it on Io! A slow-paced introduction to the Io language […]


Comments are closed.