Previous section   Next section

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

Table of Contents
Chapter 7.  Procedures and Scope

Call by Name Using upvar

Use the upvar command when you need to pass the name of a variable, as opposed to its value, into a procedure. The upvar command associates a local variable with a variable in a scope up the Tcl call stack. The syntax of the upvar command is:

upvar ?level? varName localvar

The level argument is optional, and it defaults to 1, which means one level up the Tcl call stack. You can specify some other number of frames to go up, or you can specify an absolute frame number with a #number syntax. Level #0 is the global scope, so the global foo command is equivalent to:

upvar #0 foo foo

The variable in the uplevel stack frame can be either a scalar variable, an array element, or an array name. In the first two cases, the local variable is treated like a scalar variable. In the case of an array name, then the local variable is treated like an array. The use of upvar and arrays is discussed further in Chapter 8 on page 92. The following procedure uses upvar to print the value of a variable given its name.

Example 7-5 Print variable by name.
proc PrintByName { varName } {
   upvar 1 $varName var
   puts stdout "$varName = $var"

You can use upvar to fix the incr command. One drawback of the built-in incr is that it raises an error if the variable does not exist. We can define a new version of incr that initializes the variable if it does not already exist:

Example 7-6 Improved incr procedure.
proc incr { varName {amount 1}} {
   upvar 1 $varName var
   if {[info exists var]} {
      set var [expr $var + $amount]
   } else {
      set var $amount
   return $var

      Previous section   Next section