[Zarutian] 18. november 2005: TeaTime is the underlying object system of Croquet. (Or that is as much as I gather) see http://www.opencroquet.org/Croquet_Technologies/architecture.html for more details. And the code below was inspired by the TeaTime concept: # below code by Zarutian is hereby in the public domain proc thingy {name} { proc $name args "namespace eval $name \$args" } proc trackedThingy {name} { proc $name args [string map [list @name $name] { namespace eval @name lappend __history [list $args] namespace eval @name set this @name namespace eval @name $args }] $name proc undo {} { # there is a potential proplem with this proc # it doesnt notify subcomponents of the undo # possible solution would be adding an element # to each element of __history that stated what # other objects were affected variable __history variable this set local_this $this set local_history $__history if {[llength $__history] > 2} { namespace delete [namespace current] if {[lindex $local_history end] == "undo"} { set local_history [lrange $local_history 0 end-1] } foreach invocation [lrange $local_history 0 end-1] { eval [concat $local_this $invocation] } } else { # err here or not? } } } proc replicatedThingy {name connector} { proc $name args [string map [list @name $name @connector [list $connector]] { if {![was-called-by? @connector]} { # to prevent invocation feedback (similiar to acaustic feedback) @connector invoke @name $args } namespace eval @name $args }] } proc was-called-by? {commandName} { set callstack [list] for {set i [info level]} {$i >= 0} {incr i -1} { lappend callstack [info level $i] } foreach call $callstack { if {[lindex $call 0] == $commandName} { return yes } } return no } Some of the above code might be more at home elsewhere.