Synopsis edit
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 edit
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.
Anonymous comment 2016-05-02: The impact of this wart can be reduced somewhat with
-map:
...
proc _set {name val} {
...
namespace ensemble create -map {set _set get get}
WHD: Another way to convenient create an ensemble is to use a
[snit::type
] as a singleton. It's a namespace ensemble under the covers, but avoids the "set" problem described above, and allows easy delegation of methods. The main trick is to disable the creation of instances of the type:
snit::type myensemble {
pragma -hasinstances no
typemethod set {key value} { ... }
}
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 edit