= to assign a value to a slot on an object.
:= to assign a value on a slot or create a new value.
::= to assign a value to a slot, create setters for that slot or assign a new value.
I mentioned the concept of a slot here. This is a crucial feature of Io. It’s quite similar to Ruby. You can send a message to an Io object and it will do 1 of a couple things:
It looks like this in the code:
duck := Object cloneduck quack := writeln("quack quack")duck quack// => quack quack
Here we are defining an
Object is the base prototypical object in Io. Say we sent a message to the duck object to figure out what kind of animal it was.
duck := Object cloneduck type// => Object
You can see that we get
Object back. We didn’t actually assign this slot to duck so where did Io get this value? This is where Prototypal Inheritance comes in. If that message isn’t on the object, Io will pass that message to its parent object to see if it exists. So if we change the object that duck inherits from, that will be the first object that Io passes messages to.
Animal := Object cloneduck := Animal cloneduck type// => Animal
This is how we can share behavior between objects:
Animal := Object cloneAnimal meow := writeln("meow")duck := Animal cloneduck meow// => meow
Ducks shouldn’t meow, but you get the idea.
A special feature of Io is how it treats evaluating its messages. Most languages will evaluate the parameters passed to values and assign those values to memory ahead of time. Io doesnt do this and it is an important destinction. An example that Bruce Tate uses in 7 Programming Languages in 7 weeks is defining an
unless := method((call sender doMessage(call message argAt(0))) ifFalse(call sender doMessage(call message argAt(1))) ifTrue(call sender doMessage(call message argAt(2))))duck := Object cloneduck isABird := trueunless(duck isABird, write("Oh No, Im not a bird\n"), write("Yay, I am a bird\n"))
Theres a lot going on here but the key point is you can pass any message into the first parameter of unless and this function will delay the execution of the parameters. You can see that a duck is a bird, so the
ifTrue block gets called, writing out
Yay, I am a bird. If Io was evaluating all the parameters,
Oh No, Im not a bird would have been written out.
Co-routines are useful for suspending your progams execution so that the thread can do something else. This is useful when you have to make some sort of asyncronous request or expensive task. You can
yield so that the asyncronous opertion happens and will be available when your program comes back to your function.
Bruce Tate gave a nice example in his book:
vizzini := Object clonevizzini talk := method("Fezzik, are there rocks ahead?" printlnyield"No more rhymes now, I mean it." printlnyield)fezzik := Object clonefezzik rhyme := method(yield"If there are, we'll all be dead." printlnyield"Anybody want a peanut?" println)vizzini @@talk; fezzik @@rhymeCoroutine currentCoroutine pause// =>Fezzik, are there rocks ahead?If there are, we'll all be dead.No more rhymes now, I mean it.Anybody want a peanut?Scheduler: nothing left to resume so we are exiting---------Coroutine callStack A4_Exception.io 244Coroutine backTraceString A4_Exception.io 274Coroutine showStack A4_Exception.io 177Coroutine pause Actor.io 150Object actorProcessQueue Actor.io 115
Here we define two regular objects both with methods that print things. You’ll notice the
yield syntax. This is how you tell Io where your program will halt its execution and let other operations happen. The other important syntax is the
@@. This tells Io to execute that message in its own thread. As you can see the strings being printed are alternating from
fezzik back to
vizzini and then
fezzik. We have to through in
Coroutine currentCoroutine pause so our program doesnt exit before the threads are done.
Heres what happens when you run the code regularly:
vizzini := Object clonevizzini talk := method("Fezzik, are there rocks ahead?" printlnyield"No more rhymes now, I mean it." printlnyield)fezzik := Object clonefezzik rhyme := method(yield"If there are, we'll all be dead." printlnyield"Anybody want a peanut?" println)vizzini talk; fezzik rhyme// =>: Fezzik, are there rocks ahead?: No more rhymes now, I mean it.: If there are, we'll all be dead.: Anybody want a peanut?
You can see that Io ignores the
Io has an extremely small footprint and flexible enough to describe an domain specific language. It’s really cool to see how such different programming languages work.