[NEM] ''6 Oct 2006'': While contemplating all things [OO] and [TIP] 257 [http://tip.tcl.tk/257], I came across an interesting interaction between features available in Tcl 8.5. It is possible to use [namespace ensemble] without needing any namespace to back it up! In particular, the -map option can be used to model simple slot-based objects. Together with the [apply] command, methods can then be added. To demonstrate, let's consider writing a simple stateless object to represent a rectangle on a canvas: proc rect {canv x0 y0 x1 y1} { set id [$canv create rect $x0 $y0 $x1 $y1] namespace ensemble create -command $canv.rect$id \ -map [dict create id [list const $id] \ coords [list const [list $x0 $y0 $x1 $y1]]] } proc const val { return $val } We now have a simple constructor that creates a rectangle on a canvas and creates an object command for that rectangle, with two ''slots'' to get the canvas id and coordinates associated with the rectangle: pack [canvas .c] set r [rect .c 20 20 100 100] puts "id = [$r id], coords = [$r coords]" These slots are just entries in the -map of the ensemble that alias to the "const" command to simply return their value. Note that ''no namespace is involved at all!'' We can write a general method for creating slot aliases on these objects: proc alias {object slot command args} { set map [namespace ensemble configure $object -map] dict set map $slot [linsert $args 0 $command] namespace ensemble configure $object -map $map } We can now add extra slots to the rectangle object: alias $r type const "rectangle" puts "$r is a [$r type]" Using anonymous functions via [apply] in 8.5, we can even add new methods to the object. These are simply aliases to an anonymous function. We add a "self" parameter and arrange for it to be filled with the object command: proc method {object name params body} { set params [linsert $params 0 self] alias $object $name ::apply [list $params $body ::] $object } method $r width {} { lassign [$self coords] x0 y0 x1 y1 expr {abs($x1-$x0)} } method $r height {} { lassign [$self coords] x0 y0 x1 y1 expr {abs($y1-$y0)} } We can even add method and alias as methods on the object itself: alias $r method ::method $r alias $r alias ::alias $r $r method area {} { expr {[$self width] * [$self height]} } puts "area = [$r area]" We could add mutable slots by creating a slot alias that can rewrite itself. This seems to be a fascinating new way of creating relatively ''lightweight'' objects, benefiting from the fast [namespace ensemble] mechanism, without having the overhead of an actual namespace. ---- [[ [Category Object Orientation] | [Category Example] ]]