Version 23 of Variable Substitution

Updated 2015-02-12 21:06:06 by pooryorick

Variable substitution, one of the substitutions defined in the dodekalogue, is one of the mechanisms for retrieving the value of variables in Tcl.

set v aValue
puts $v

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

aValue

The $ notation was added to Tcl for coding convenience and is short for

set v

The following lines are equivalent:

puts $v
puts [set v]

When dynamically composing 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, but 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}

Using set in place of the $ variable can help to illuminate the behaviour of Tcl. The following line pairs are equivalent:

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

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

When accessing an array variable, the member name is computed and then looked up in the array, so arrays are a good fit when programming in a style that leads to composition of variable names:

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 [set var([set i])]}

Although there are often better alternatives to variable indirection, it can be implemented in the following ways:

set a something
set pointer a
puts [set $pointer] ;#good style
puts [set [set pointer]] ;#more verbose style
eval puts \$$pointer ;#oh blimey, it's "eval"!  Run away!

Array Variables

Variable substitution is not symmetrical with set in its syntax. This is because set has the luxry of knowing where the word ends, while variable substitution, which may be interpolated into another string, does not.

set var(one)two) three
#doesn't work, because Tcl sees $var(one)
puts $var(one)two) 

Using braces solves the problem in this particular case:

puts ${var(one)two)}

Of course, it's always possible to use set:

puts [set var(one)two)]

See also

set
variable
double substitution and Dereferencing
how do i do $$var - double dereferencing a variable
Variable substitution in -command scripts
Quoting Hell