7.23.2006
2:39 AM

Okay, so I've been putting some thought into encapsulation in Io. With a lack of namespaces, avoiding clutter and name collisions becomes fairly tough. For example, this does not work:

Math := Object clone do(
    PI := 3.14159265
    Circle := Object clone do(
        newSlot("radius")
        with := method(r,
            self clone setRadius(r)
        )
        area := method(
            PI * radius^2
        )
        circumference := method(
            2 * PI * radius
        )
    )
)

Math Circle with(5) area println
# Exception: Circle does not respond to 'PI'

Clearly there is a problem here. In 'area', I try to refer to PI, which resides in the same "namespace" as Circle. That's not how Io resolves names, though. It looks up names through an object's protos, and Math is simply not in there. So what we need to do is append Math to Circle's protos:

Math := Object clone
Math do(
    PI := 3.14159265
    Circle := Object clone appendProto(Math) do(
        newSlot("radius")
        with := method(r,
            self clone setRadius(r)
        )
        area := method(
            PI * radius^2
        )
        circumference := method(
            2 * PI * radius
        )
    )
)

Math Circle with(5) area println
# 78.539816

Yeah, that seems to work, but it is pretty clear that explicitly adding the namespace is a lot of repetition, if you have a lot of objects within the namespace, and you have to define the namespace over two lines so that it can refer back to itself. So I defined a new Namespace object that creates its own Object prototype. When a new Namespace is cloned, it defines a new Object and appends itself to its prototypes:

Namespace := Object clone do(
    init := method(
        self Object := Object clone appendProto(self)
    )
)

Fairly simple. Now, to make use of it:

Math := Namespace clone do(
    PI := 3.14159265
    Circle := Object clone do(
        newSlot("radius")
        with := method(r,
            self clone setRadius(r)
        )
        area := method(
            PI * radius^2
        )
        circumference := method(
            2 * PI * radius
        )
    )
)

Math Circle with(5) area println // 78.539816

There! Nice and clean. Happy Ioing!