Version 6 of Ensemble objects

Updated 2015-01-23 11:09:50 by aspect

Synopsis

A (mostly) better alternative to namespace ensemble:

oo::object create stash 
oo::objdefine stash {
    variable Stash
    method set {name val} {
        set Stash($name) $val
    }
    method get {name} {
        return $Stash($name)
    }
}

A few things are noteworthy:

  • we didn't define a class! TclOO lets us define oo::objdefine methods directly on any object.
  • methods don't get in the way of command resolution inside the object: we can call set without worrying that a method set exists. To call other commands within the ensemble, just use my
  • we have no control over the object's namespace. This is mildly dissatisfying compared to ensembles, but self namespace is better than a hardcoded reference -- it makes each method copy&paste-portable to other objects

Rationale

Historically, namespace ensembles have been plagued with one wart: command resolution starts in the ensemble's namespace. Thus, subcommands with names like set are problematic:

namespace eval stash {
    proc set {name val} {
        variable Stash
        set Stash($name) $val
    }
    proc get {name} {
        variable Stash
        return $Stash($name)
    }
    namespace export *
    namespace ensemble create
}

This example will fail, because stash set accidentaly calls itself! This can be worked around by using ::set, but such changes are ugly. And not just cosmetically: try extending an existing ensemble with a set method, or gracefully using namespace path.

TclOO provides a neat solution to this: simply use an object.

TODO

Nested ensemble objects (hint: oo::objdefine forward). More rationale? Link some of the wart discussions here for a solution (and clean them up).

See Also