[ulis], 2003-08-31 ---- '''See also''' * [set] * [variable] * [double substitution] and [Dereferencing] * [how do i do $$var - double dereferencing a variable] * [Variable substitution in -command scripts] ---- 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 (here the value is "aValue"). The $ notation was added to Tcl to simplify the codification and is not needed. The set command (with one argument) returns the value of a variable. And the two following lines are equivalent: puts $v puts [set v] Sometimes the $ notation can't be used without difficulty. This is when the name of the variable is composed from other variables: foreach i {1 2 3} { set var$i value$i } foreach i {1 2 3} { puts $var$i } <-- this fails (var is undefined) ---- [TV] It fails, logically speaking, because you are trying to do two evaluation steps in a certain order while your syntax puts them on the same level. What you want is to evaluate what the string concatenation of 'var' with the content of variable i becomes, and get the content of the variable with the resulting name. Not in hell, and not unlogically, though possibly prone to syntactical issues (like special characters), you could rightfully and reasonable write: foreach i {1 2 3} { eval puts "\$var$i" } 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 (var is undefined) The last line fails because Tcl tries to substitute $var and then $i, and finds that var is not defined. The right solution is to use set: foreach i {1 2 3} { puts [set var$i] } Here Tcl substitutes the value of i and then set returns the value of var1, var2, var3. 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 (var is undefined) foreach i {1 2 3} { puts [$ var][$ i] } <-- this fails (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]