Tcl trace Command
last modified October 20, 2026
The Tcl trace command monitors variables (and also commands and
script execution) for specific operations. This article covers variable traces.
It allows executing custom scripts when variables are accessed or modified.
This powerful feature enables debugging and reactive programming patterns.
Basic Definition
The trace command sets up callbacks for variable operations.
These operations are read, write, unset
and, for arrays, array (the use of an array command).
Syntax: trace add variable name ops command. The ops argument is a
list of operations, and the command is a command prefix that Tcl calls with the
variable name, the array index and the operation appended. Multiple traces
can be added to the same variable.
Simple Variable Write Trace
This example demonstrates tracing write operations on a variable.
proc traceWrite {varName index op} {
upvar 1 $varName v
puts "Variable $varName was modified"
puts "New value: $v"
}
set x 10
trace add variable x write traceWrite
set x 20
set x 30
The traceWrite procedure is called whenever x is
modified. It receives the variable name, array index (empty for scalars),
and operation type. The procedure runs in its own scope, so it uses
upvar 1 to reach the traced variable by name. This helps track
all changes to the variable.
Read Operation Tracing
This example shows how to trace when a variable is read.
proc traceRead {varName index op} {
puts "Variable $varName was read"
}
set y 100
trace add variable y read traceRead
puts "Value: $y"
set z [expr {$y + 50}]
The traceRead procedure executes whenever y is
accessed. This helps monitor all read operations, useful for debugging
or implementing computed properties.
Array Element Tracing
Traces work with array elements similarly to scalar variables.
proc arrayTrace {arrName index op} {
upvar 1 $arrName arr
puts "Array $arrName\($index) operation: $op"
if {$op eq "write"} {
puts "New value: $arr($index)"
}
}
array set colors {red #ff0000 green #00ff00}
trace add variable colors write arrayTrace
trace add variable colors read arrayTrace
set colors(blue) #0000ff
puts $colors(green)
This traces both read and write operations on array elements. The
index parameter contains the array key being accessed.
The upvar 1 command is needed to access the array from the
trace procedure.
Unset Operation Tracing
Traces can detect when variables are unset, including when a local variable is destroyed because its procedure returned.
proc traceUnset {varName index op} {
puts "Variable $varName is being unset"
}
set temp "temporary value"
trace add variable temp unset traceUnset
unset temp
The traceUnset procedure executes after the variable
has been removed, so it can no longer read the old value. This allows cleanup
operations or logging when variables are destroyed.
Multiple Traces on Single Variable
Multiple traces can be added to the same variable for different operations.
proc writeHandler {varName index op} {
upvar 1 $varName v
puts "WRITE: $varName changed to $v"
}
proc readHandler {varName index op} {
puts "READ: $varName was accessed"
}
set counter 0
trace add variable counter write writeHandler
trace add variable counter read readHandler
incr counter
set x [expr {$counter * 2}]
This example adds separate traces for read and write operations.
The handlers provide different output for each operation type. The
incr command reads the variable before it writes it, which is why
"READ" is printed before "WRITE". If several traces match the same operation,
the one added last runs first.
Removing Traces
Traces can be removed when they're no longer needed.
proc logChange {varName index op} {
puts "Change detected in $varName"
}
set debugVar "test"
trace add variable debugVar write logChange
set debugVar "new value"
trace remove variable debugVar write logChange
set debugVar "no tracing now"
The trace remove command stops the tracing. After removal,
variable operations no longer trigger the callback, so the last assignment
prints nothing. The same arguments (operations and command) that were given to
trace add are needed to remove the trace. Removing traces avoids
needless overhead and unwanted side effects.
Best Practices
- Performance: Use traces sparingly as they add overhead.
- Debugging: Traces are excellent for debugging variable changes.
- Cleanup: Remove traces when they're no longer needed.
- Scope: The trace command runs in its own scope; use
upvar 1or a qualified name to reach the variable. - Recursion: Avoid infinite recursion in trace callbacks.
This tutorial covered the Tcl trace command with practical
examples showing its usage for monitoring variable operations.
Author
List all Tcl Tutorials.