Io in 10 minutes
I try (not very well) to explain Io, a small language, a la X in Y minutes
, as much as I know anyway
This is mostly a recollection from old notes, I wanted to get it all in one place (another place, perhaps).
The real Io tutorial is at least as good, let’s just be clear. This is just a blog.
First, some wordy explainy parts, then below that code
just like X in Y minutes
.
Io, in words
- all values are objects, all actions are messages
- objects are prototypes, & classes, & namespaces, & contexts
- blocks are functions, & methods, & closures
- messages are operators, & calls, & assigns, & accesses
- objects are:
- lists of slots, which are key/value pairs
- list of protos, which are objects from which it inherits
- prototype objects, usually Uppercase, have a
clone
slot - when an object is cloned, its init slot is called
- messages will route to the object’s slots, then each of its protos’ slots until a matching slot is found. This is fully dynamic and happens entirely at runtime.
- Io has no globals. The toplevel is an object called the Lobby.
-
Slots can be created by assigning to them.
Obj slot := value
-
methods are anonymous functions that take a message for a receiver, create a locals object, and assign the
proto
&self
slot to the receiver.method("hello!" print)
- methods return their last value by default
-
methods can take many arguments
method(a, b, c, d, a*d - b*c)
- blocks are basically methods, except their context is lexically-bound not to the receiver/target, but to the context where the block was created
- for either blocks/methods, its
call
slot holds information about the block/method activation:sender
,message
,target
,slotContext
,activated
- an object can both receive & pass a message with
resend
. This will forward the same message to a proto.
Io, in plain sight
I haven’t double-checked all of this code, so I apologize if I’ve screwed anything up.
#
# Primitives, literals, declarations, assignments, I/O
#
true
false
nil
1
2.0
1 + 2.0
2 / 3.0
"hello?"
list(1, 2, "3")
# lists are heterogenous
x := 1
# x is declared with :=
x = 2
# x is updated with =
"hello, world!" println
"X = #{x}" interpolate println
# "X = 2"
square := method(x, x*x)
"#{x}^2 = #{square(x)}" interpolate println
# "2^2 = 4"
("pine" .. "apple") println
# "pineapple"
(if(1 < 2, "1", "2") .. " is smaller") println
# if is an expression
"X is #{x} before the loop" interpolate println
while(x < 5, x = x + 1)
"X is #{x} after the loop" interpolate println
for(i, 1, 10, i print)
# 12345678910
for(i, 1, 10, 3, i print)
# 14710
fibonacci := method(n,
if(n < 2,
1,
fibonacci(n - 2) + fibonacci(n - 1)
)
)
fibonacciIterative := method(n,
a := 0;
b := 1;
for(i, 1, n,
next := a + b;
a := b;
b := next
);
b
)
Date cpuSecondsToRun(fibonacci(25)) println
Date cpuSecondsToRun(fibonacciIterative(25)) println
#
# Objects & slots, in more detail
#
Object
Object clone
# different IDs
Object clone
Object sneeze := method("Achoo!" println)
Object sneeze
Object getSlot("sneeze")
# get the method, don't invoke it
Object getSlot("sneeze") code
# ..yeah
Lobby
Lobby slotNames
slotNames
3 slotNames
3 proto
3 proto slotNames
"A string" proto
"A string" protos
#
# Message passing, in more detail
#
Knock := Object clone
Knock whoIsIt := method(call sender)
Knock whoAmI := method(call receiver)
Knock whatIsIt := method(call message name)
Knock whatAboutIt := method(call message arguments)
Knock whoIsIt
Knock whoAmI
Knock whatIsIt
Knock whatAboutIt
Knock whatAboutIt()
Knock whatAboutIt(2, 3, x)
Knock sayX := method(x println)
SpecialContext := Object clone
SpecialContext x := "special"
Knock sayX
SpecialContext Knock sayX
SpecialContext Knock whatAboutIt(2, 3, x)
#
# Some "built-ins", provided you've got the JSON extension :P
# these probably won't work without it
#
list(1, 2, 3) println
list(1, 2, 3) asJson println
list(3, 1, 2) sort println
list(1, 2, 3) sum println
Config := Object clone
Config version := "1.0"
Config name := "io-language"
Config asJson println
Again I’m not sure 100% of the above even “interprets”, so to speak.
I would really like to expand a bit more, on maps, file/http I/O, coroutines. And fix any mistakes.
Sometimes, I get a segfault running these examples through io, but I’m not really sure if it’s user error or what. I’ll figure it out.