Tcl upvar Command
last modified April 3, 2025
The Tcl upvar command creates a link to a variable in a different
scope. It allows procedures to modify variables in their caller's scope.
This is essential for implementing pass-by-reference semantics in Tcl.
Basic Definition
The upvar command creates a reference to a variable from a higher
stack frame. It enables procedures to modify variables in their caller's scope.
Syntax: upvar ?level? otherVar myVar ?otherVar myVar ...?. The level
specifies how many frames up to look for the variable. Default is 1 (caller).
Simple Variable Reference
This example shows basic usage of upvar to modify a variable in the
caller's scope.
proc increment {varName} {
    upvar $varName var
    incr var
}
set counter 0
increment counter
puts "Counter is now $counter"
The increment procedure uses upvar to create a local
reference to the caller's variable. The incr command modifies it.
Modifying Array Elements
upvar can also be used to modify array elements in the caller's scope.
proc updateArray {arrName key} {
    upvar $arrName arr
    set arr($key) [expr {$arr($key) * 2}]
}
set numbers(one) 1
set numbers(two) 2
updateArray numbers one
puts "Array element: $numbers(one)"
This demonstrates how upvar can reference an entire array. The
procedure doubles the value of the specified array element.
Multiple Level References
The level parameter allows accessing variables from higher stack frames.
proc outer {} {
    set x 10
    inner
    puts "Outer x: $x"
}
proc inner {} {
    upvar 2 x y
    set y 20
}
outer
Here, inner modifies a variable two frames up the call stack.
The upvar 2 command creates a reference to x in
outer's scope.
Passing Variables by Reference
upvar enables pass-by-reference semantics in Tcl procedures.
proc swap {a b} {
    upvar $a x $b y
    set tmp $x
    set x $y
    set y $tmp
}
set first "apple"
set second "orange"
swap first second
puts "First: $first, Second: $second"
This implements a classic swap operation using upvar. The procedure
swaps the values of two variables in the caller's scope.
Default Level Behavior
When no level is specified, upvar defaults to level 1 (caller's scope).
proc modifyVar {varName} {
    upvar $varName localVar
    set localVar "modified"
}
set original "initial"
modifyVar original
puts "Variable is now: $original"
This shows the default behavior where upvar references the immediate
caller's scope. The procedure modifies the variable in its direct caller.
Global Variables with upvar
upvar can access global variables by specifying level #0.
proc accessGlobal {} {
    upvar #0 ::globalVar localVar
    set localVar "global value"
}
set globalVar "initial"
accessGlobal
puts "Global variable: $globalVar"
This demonstrates accessing a global variable using upvar #0.
The procedure modifies the global variable through a local reference.
Best Practices
- Explicit Levels: Specify levels clearly for readability.
- Variable Names: Use descriptive names for references.
- Scope Awareness: Be mindful of which scope you're modifying.
- Global Variables: Prefer parameters over global access.
- Documentation: Document reference parameters clearly.
This tutorial covered the Tcl upvar command with practical
examples showing its usage for variable references across scopes.
Author
List all Tcl Tutorials.