if 0 {[Richard Suchenwirth] 2005-03-25 - [TOOT] is "transparent [OO] for [Tcl]" - a "pure-value" approach, where a value (a [list]able string) like {Foo | bar grill} is interpreted to be of class ''Foo'' (so ''Foo'''s methods can be applied to it), with the "instance variable" values ''bar'' and ''grill'. (In fact, they aren't "variable" - values are immutable). The "|" as second element just identifies this as a TOOT value. "Transparent" means that a TOOT has nothing to hide - its state is fully visible in the string representation. For a "constructor", [list] is sufficient: set c [list Complex | $real $imag] but a few keystrokes add "constructor sugar", so you might as well call set c [Complex | $real $imag] No [garbage collection] is necessary: like all Tcl values, TOOT values just go away when nobody wants them any more (e.g. on [return] when associated with a local variable). Methods are called as usual, with the method name (which can also look like "+") after the object, and then possibly more arguments. The example with the multiplication method named, evidently, "*" shows that the appearance of infix arithmetics comes as a by-product: set i {Complex | 0 1} ;#-- imaginary unit i $i * $i ==> {Complex | -1 0} ;#-- such that i*i == -1 Reinventing [Complex math made simple], here's my experiments. Binary operators take one argument, which can be another Complex, or a real number x, which then gets "upgraded" to [[Complex | $x 0]]. A single [proc] contains all methods for the Complex "class": } proc Complex {| r i {method ""} args} { if {[llength $args]==1} { set operand [lindex $args 0] if [string is double -strict $operand] { set r2 $operand; set i2 0 } else {foreach {Complex | r2 i2} $operand break} } switch -- $method { "" {list Complex | $r $i ;#--constructor sugar} real {set r} imag {set i} abs {expr {hypot($i,$r)}} arg {expr {atan2($i,$r)}} format {expr {$i ? "$r+i*$i" : $r}} == {expr {$r==$r2 && $i==$i2}} != {expr {!($r==$r2 && $i==$i2)}} + {Complex | [+ $r $r2] [+ $i $i2]} - {Complex | [- $r $r2] [- $i $i2]} * {Complex | [expr {$r*$r2 - $i*$i2}] \ [expr {$r*$i2 + $r2*$i}] } / {set div [expr {$r2*$r2 + $i2*$i2}] Complex | [expr {($r*$r2 + $i*$i2) / $div}] \ [expr {($r2*$i - $r*$i2) / $div}] } default {error "unknown method $method"} } } #-- For convenience, [expr] operators are exported as commands: foreach op {+ - * /} {proc $op {a b} "expr {\$a $op \$b}"} if 0 {To make this flavor of TOOT work, we [let unknown know] it shall auto-expand the first word if its second element is "|" :} proc know what {proc unknown args $what\n[info body unknown]} know { if {[lindex $args 0 1] eq "|"} { return [uplevel 1 [lindex $args 0] [lrange $args 1 end]] } } #-- This little tester reports the unexpected proc ? {cmd expected} { catch {uplevel 1 $cmd} res if {$res ne $expected} {puts "$cmd -> $res, expected $expected"} } #-- The test suite passes silently when all goes well: set i {Complex | 0 1} ;# flat value set b [Complex | 3 4] ;# constructor sugar ? {$b format} {3+i*4} ? {$b abs} 5.0 ? {$b real} 3 ? {$b imag} 4 ? {$i == $i} 1 ? {$i == $b} 0 ? {$i != $b} 1 ? {$i + $b} {Complex | 3 5} ? {$b - $i} {Complex | 3 3} ? {$b + 1} {Complex | 4 4} ? {$i * $i} {Complex | -1 0} ;# i**2 == -1? ? {[$i * $i] format} -1 set r [$b abs] set phi [$b arg] ? {[[Complex | [expr cos($phi)] [expr sin($phi)]] * $r] == $b} 1 ? {$b / 0} "divide by zero" ? {$b / {Complex | 0 0}} "divide by zero" ? {$a foo} "unknown method foo" if 0 { See also [Straightforward implementation of complex numbers] which is included in recent [Tcllib] ---- [Category Object Orientation] | [Arts and crafts of Tcl-Tk programming] }