Toasters and things

Richard Suchenwirth 2000-12-12 - In On things, a very simple and pretty dynamic OO API for Tcl was described. For tentative implementations see Doing things and my latest state, Doing things in namespaces. In order to see what can (and what cannot) be done with these things, I looked at the class man page from [incr Tcl] 3.1, where in the end, under CHAINING METHODS/PROCS, the famous toaster example was given in Itcl.

You create a Toaster class, with toast and clean methods and a crumb count that will burn the toaster if too high. Itcl:

 class Toaster {
          variable crumbs 0
          method toast {nslices} {
              if {$crumbs > 50} {
                  error "== FIRE! FIRE! =="
              }
              set crumbs [expr $crumbs+4*$nslices]
          }
          method clean {} {
              set crumbs 0
          }
  }

In Things, ways ("methods") are defined outside the "class" declaration, so you can add ways and properties ("variables" - just by setting them) at any time, while in Itcl a class (including its methods and variables) can only be defined once. In exchange, accessing a thing's variables requires referring to self:

 thing new Toaster crumbs 0

 Toaster wayto toast {{self nslices} {
    if {[$self crumbs]>50} {
         error "$self:=== FIRE! FIRE! ==="
    }
    $self set crumbs [expr [$self crumbs]+4*$nslices]
   }   
 }
 Toaster wayto clean {{self} {$self set crumbs 0}}

Next comes a smart toaster, that acts like a normal one except that it cleans itself if the crumb count gets dangerously high. Itcl:

 class SmartToaster {
          inherit Toaster
          method toast {nslices} {
              if {$crumbs > 40} {
                  clean
              }
              return [Toaster::toast $nslices]
              # alternatively: return [chain $nslices]
         }
      }

Things (I still have to think on how to emulate the chain command):

 Toaster new SmartToaster ;# inheritor in front

 SmartToaster wayto toast {{self nslices} {
   if {[$self crumbs]>40} {
          $self clean
    }
    ::thing::Toaster::toast $self $nslices
   }   
 }
 SmartToaster new T1 ;# create an "object" with the 'new' way
 T1 toast 3 ;#...

Pretty similar at first glance, and in operation, Toasters and SmartToasters behave like I'd expect them to (and both Itcl's and Things' SmartToasters may burn if you toast more than three slices in one go...). But what I like most about those Things: it took 2 pages of Tcl code (see Doing things in namespaces) to get'em going ...;-)


A modified version (see Chaining things) allows chaining, in the form

 SmartToaster wayto toast {{self nslices} {
   if {[$self crumbs]>40} {
          $self clean
    }
    ::thing::chain $nslices
   }   
 }

SS 9Apr2005: what about a more smalltalkish solution where every thing has a parent method, so that instead of:

  ::thing::chain $nslices

it is possible to write

  $self parent toast $nslices?

RS Makes sense - except that mentioning the name of a method inside its body is a bit risky if you change the name outside but not inside.