Version 14 of Variable Substitution

Updated 2013-02-20 15:34:23 by pooryorick

ulis, 2003-08-31

See also

Variable substitution is the way Tcl gets a value from a name:

set v aValue
puts $v

The $v notation tells Tcl to get the value of the variable v, whose value is

aValue

The $ notation was added to Tcl for coding convenience as a shorter way to express

set v

The following lines are equivalent:

puts $v
puts [set v]

When dynamically compoing a variable name, set can be used where $ can't. In the following example, Tcl substitutes the value of i and then set returns the value of var1, var2, var3.

foreach i {1 2 3} { puts [set var$i] }

The following code fails because Tcl tries to substitute $var and then $i, and finds that var is not defined.

#warning: example of bad code
foreach i {1 2 3} { puts $var$i } ;# this fails because $var is undefined

Another approach that is not recommended:

foreach i {1 2 3} {eval puts \$var$i}

though possibly prone to syntactical issues (like special characters), you could rightfully and reasonable write:

without the extra 'eval', which evaluates its argument list once, you'd get the logical and desirable intermedeate result:

% foreach i {1 2 3} { puts "\$var$i" }
$var1
$var2
$var3
foreach i {1 2 3} { set var$i value$i }
foreach i {1 2 3} { puts $var$i } ;# this fails because $var is undefined(var is undefined)

To best understand what happens when Tcl is substituting variables let's define a $ alias that does the $ substitution:

interp alias {} $ {} set

Replacing the $ notation by a $ call, the following lines are equivalent two by two:

foreach i {1 2 3} {puts $var$i} ;# this fails because $var is undefined
foreach i {1 2 3} {puts [$ var][$ i]} ;# this fails because $var is undefined

foreach i {1 2 3} {puts [set var$i]}
foreach i {1 2 3} {puts [$ var[$ i]]}

Composing the name of a variable is a clear signal that an array could be used:

foreach i {1 2 3} {set var($i) value$i}
foreach i {1 2 3} {puts $var($i)}

The last line is equivalent to:

foreach i {1 2 3} {puts [$ var([$ i])]}

TV It could also indicate an indirection, an important programming concept, and in some form a major language discussion issue in the history of tcl/tk:

set a something
set pointer a
eval puts "\$$pointer"

ulis The last line is equivalent to:

puts [set [set pointer]]

^-amended slightly by FW

And can be rewritten, avoiding eval:

puts [set $pointer]