Seven Languages in Seven Weeks: Day 6

Last day of Io and what do we have? A small snippet that adds [1, 2, 3] style array literals to the language. Kind of neat that you can do it... also the kind of thing that can almost certainly get you in trouble.

squareBrackets := method(
    lst := List clone
    call evalArgs foreach(arg,
        lst append(arg)
    )
    return lst
)

... and here's a Builder that lets you create XML documents by dynamically translating messages into XML elements.

Builder := Object clone
Builder forward := method(
    node := Element new(call message name)
    call message arguments foreach(arg,
        content := self doMessage(arg)
        if(content type == "Sequence",
            node addChild(TextNode new(content)),
            node addChild(content)
        )
    )
    return node
)

Node := Object clone
Node indent := method(depth,
    return "\t" repeated(depth)
)

TextNode := Node clone
TextNode new := method(text,
    node := TextNode clone
    node text := text
    return node
)

TextNode render := method(depth,
    writeln(self indent(depth), self text)
)

Element := Node clone
Element new := method(name,
    other := self clone
    other attrs := Map clone
    other name := name
    other children := List clone
    return other
)

Element addChild := method(child,
    self children append(child)
)

Element attr := method(k, v,
    self attrs atPut(k, v)
    return self
)

Element fmtAttrs := method(
    if(self attrs isEmpty,
        return "",
        return " " with(self attrs map(k, v,
            k with("=\"", v, "\"")
        ) join(" "))
    )
)

Element render := method(depth,
    writeln(indent(depth), "<", self name, self fmtAttrs, ">")
    self children foreach(child,
        child render(depth + 1)
    )
    writeln(indent(depth), "</", self name, ">")
)

... and a Builder document ends up looking like this:

Builder ul(
    li("some text") attr("class", "first"),
    li("some more text"),
    li("even more text") attr("class", "last")
) attr("class", "fancy") attr("id", "menu") render(0)

Seven Languages in Seven Weeks: Day 5

Have you ever wanted some bastard to redefine division on you? I haven't either, but if it ever comes up, you can totally do it in Io:

Number trueDiv := Number getSlot("/")
Number / = method(n,
    if(n == 0,
        return 0,
        return self trueDiv(n)
    )
)

... and here's something that approaches useful: A two-dimensional matrix class that's backed by a one-dimentional list. It includes getter, setter and iterator methods. Yay!

Matrix := Object
Matrix dim := method(x, y,
    self width := x
    self height := y
    self buffer := list()
    self buffer setSize(x * y)
)

Matrix checkBounds := method (x, y,
    if(x >= width or y >= height,
        Exception raise("index out of bounds")
    )
)

Matrix get := method(x, y,
    checkBounds(x, y)
    return self buffer at(x + y * width)
)

Matrix set := method(x, y, value,
    checkBounds(x, y)
    self buffer atPut(x + y * width, value)
)

Matrix forEach := method(f,
    for(y, 0, height - 1,
        for(x, 0, width - 1,
            f call(x, y, self get(x, y))
        )
    )
)

Seven Languages in Seven Weeks: Day 4

Io is the second language covered in Seven Languages in Seven Weeks and it is substantially further off the beaten path than Ruby was. The first day's worth of exercises didn't really have anything code snippet worthy, so here's recursive Fibonnaci to prove that I got the VM running ;-)

Fib := Object clone
Fib fib := method(n,
    if(n < 2, return 1)
    return self fib(n - 1) + self fib(n - 2)
)
Io> Fib fib(6)
==> 13