I've been thinking about how Eiffel lately and how useful class invariants were. In Eiffel, an invariant clause sets conditions that must remain true throughout the lifetime of an object. These conditions (assertions really) are bound to instance variables. Playing around with Tcl, we can come up with a useful(?) fascimile (*hack*) in just a few lines of code: proc invariant {var {expression ""} {msg "Illegal value"}} { uplevel trace variable $var w \[list invariant_check \{$expression\} \{$msg\}] } proc invariant_check {expression msg v1 v2 mode} { if {$expression == ""} { error "Cannot modify!" } if {![uplevel expr \{$expression\}]} { error $msg } } This could be very useful for Itcl (contrived example alert!): package require Itcl itcl::class Person { variable age variable sex public variable full_name constructor {name i_age i_sex} {set full_name $name} { invariant age {$age >= 0 && $age < 120} {Must be between 0 and 120.} invariant sex {$sex == "M" || $sex == "F"} {Must be M or F.} invariant full_name ;# Can never be changed!! set age $i_age set sex $i_sex } method set_age {years} { set age $years } method change_sex {mf} { set sex $mf } } So that, Person bob "Bobby Tester" 5 M bob change_sex Female ; # this will raise an error bob set_age 134 ; # this will raise an error bob configure -name "Sue" ; # this will raise an error The errors are quite useful too (for example): can't set "sex": Must be M or F. while executing "set sex $mf" (object "::bob" method "::Person::change_sex" body line 2) invoked from within "bob change_sex Female" ... Note that the 2 invariants hold across all methods in this class. The real usefulness would be in deeply complex classes where you could not guarentee that an instance variable doesn't maintain correctness through usage in derived classes. The major difference between my hack and Eiffel is that in Eiffel the variable can break the invariant clause temporarily. The clause is only checked at the end of a method's invocation. (Which we could hack here too in Tcl -- left as a later exercise). Of course, for those who don't use Itcl, this all works in plain old Tcl too... -- [Todd Coram]