Tracing Variable Values

   

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 13.  Reflection and Debugging


The trace command registers a command to be called whenever a variable is accessed, modified, or unset. This form of the command is:

 trace variable name ops command 

The name is a Tcl variable name, which can be a simple variable, an array, or an array element. If a whole array is traced, the trace is invoked when any element is used according to ops. The ops argument is one or more of the letters r, for read traces, w, for write traces, and u, for unset traces. The command is executed when one of these events occurs. It is invoked as:

 command name1 name2 op 

The name1 argument is the variable or array name. The name2 argument is the name of the array index, or null if the trace is on a simple variable. If there is an unset trace on an entire array and the array is unset, name2 is also null. The value of the variable is not passed to the procedure. The traced variable is one level up the Tcl call stack. The upvar, uplevel, or global commands need to be used to make the variable visible in the scope of command. These commands are described in more detail in Chapter 7.

A read trace is invoked before the value of the variable is returned, so if it changes the variable itself, the new value is returned. A write trace is called after the variable is modified. The unset trace is called after the variable is unset.

Read-Only Variables

Example 13-8 uses traces to implement a read-only variable. A variable is modified before the trace procedure is called, so the ReadOnly variable is needed to preserve the original value. When a variable is unset, the traces are automatically removed, so the unset trace action reestablishes the trace explicitly. Note that the upvar alias (e.g., var) cannot be used to set up the trace:

Example 13-8 Tracing variables.
 proc ReadOnlyVar {varName}{    upvar 1 $varName var    global ReadOnly    set ReadOnly($varName) $var    trace variable $varName wu ReadOnlyTrace } proc ReadOnlyTrace { varName index op }{    global ReadOnly    upvar 1 $varName var    switch $op {       w {           set var $ReadOnly($varName)       }       u {           set var $ReadOnly($varName)           # Re-establish the trace using the true name           trace variable $varName wu ReadOnlyTrace       }    } } 

This example merely overrides the new value with the saved value. Another alternative is to raise an error with the error command. This will cause the command that modified the variable to return the error. Another common use of trace is to update a user interface widget in response to a variable change. Several of the Tk widgets have this feature built into them.

If more than one trace is set on a variable, then they are invoked in the reverse order; the most recent trace is executed first. If there is a trace on an array and on an array element, then the trace on the array is invoked first.

Creating an Array with Traces

Example 13-9 uses an array trace to dynamically create array elements:

Example 13-9 Creating array elements with array traces.
 # make sure variable is an array set dynamic() {} trace variable dynamic r FixupDynamic proc FixupDynamic {name index op}{    upvar 1 $name dynArray    if {![info exists dynArray($index)]}{       set dynArray($index) 0    } } 

Information about traces on a variable is returned with the vinfo option:

 trace vinfo dynamic => {r FixupDynamic} 

A trace is deleted with the vdelete option, which has the same form as the variable option. The trace in the previous example can be removed with the following command:

 trace vdelete dynamic r FixupDynamic 

       
    Top
     



    Practical Programming in Tcl and Tk
    Practical Programming in Tcl and Tk (4th Edition)
    ISBN: 0130385603
    EAN: 2147483647
    Year: 1999
    Pages: 478

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net