** See Also ** [deref]: [Larry Smith]: A package that handles dereferencing in an orthogonal and graceful way. [handle]: [http://phaseit.net/claird/comp.lang.tcl/tcl_deref.html%|%An Essay on Tcl Dereferencing]: [how do i do $$var - double dereferencing a variable]: ** Description ** [Richard Suchenwirth] (et al) 2002-11-14: A '''reference''' is something that refers, or points, to another something (if you pardon the scientific expression). In [C], references are done with *pointers* (memory addresses); in Tcl, [handle%|%handles] are used instead. The name of a variable is used to locate (dereference) a value: ====== puts foo ;# just the string foo puts $foo ;# dereference variable with name of foo puts [set foo] ;# the same ====== This can be done more than one time by nesting `[set]`. Compare the following C and Tcl programs, that perform the same trivial task, and exhibit remarkable similarity: ======c #include int main(void) { int i = 42; int * ip = &i; int ** ipp = &ip; int ***ippp = &ipp; printf("hello, %d\n", ***ippp); return 0; } ====== ...and Tcl: ====== set i 42 set ip i set ipp ip set ippp ipp puts "hello, [set [set [set [set ippp]]]]" ====== The C asterisks correlate to `[set]` calls in derefencing, while in Tcl similar markup is not needed in declaring. But why four `[set]` evaluations for three asterisks? Because also the first mention of ''i'' in C is a dereference, to pass its value into `printf`; Tcl makes all four of them explicit (otherwise, you'd see ''hello, i''). One dereference is so frequent that it is typically abbreviated with ''$varname'', e.g. ====== puts "hello, [set [set [set $ippp]]]" ====== has `[set]` where C uses asterisks, and $ for the last (default) dereference. In Tcl, [proc%|%procedures] and [namespace%|%namespaces] each get their own table of variables. [namespace import], [upvar], and [global] allow you to link variable references to variables in command evalutions that are "higher" in the call stack, and also to variables namespaces. In C, variables in an enclosing block are automatically available in enclosed blocks, unless they are eclipsed by variable declarations in the enclosed blocks. (This little piece was written to defuse the superstition that Tcl has no references, or needs more of the same. See also [Pass by reference], which is also called "call by name", pretty exactly describes how Tcl implements it...) ---- One visitor to the [Tcl chatroom] wondered why ====== expr $$item ====== turns the value of a variable whose name is in ''item'' from 530E001 to 5300.0 - what happens is that the Tcl parser does a first derefencing, e.g., if ''item'' has the value ''ID'': ====== expr $ID ====== and `[expr]` does a [double substitution%|%kecond dereferencing] (or substitution). Not much arithmetics to do on its input (which, interpreted as a number, looks like scientific notation), but at least you get it back in canonical ''double'' representation... ---- [TV]: Dereferencing could maybe be phrased as a form of variable substitution, unless I miss some major point of the page.. Interestingly, the ideas of functional (de-) composition probably can be thought to apply practically, which in tcl normally means that the evaluation levels of a nested level command are followed in the variable substitution. ---- [MG] 2006-02-02: Here is a largely-working method of dereferencing. It allows you to do, for instance... ====== set a "some real value" set b ::a proc foo {} { global a b; puts "Value: $$b" } ====== , and get `some real value` as the result of evaluating `foo`. (It works by overloading `[proc]`, and thus anything run outside of a procedure won't have the dereferencing.) It's flaw is that it assumes (completely incorrectly) that only characters in the regexp range ====== [[:alnum:]_] ====== are valid for variable substituation after a '''$''' - this is (I think) normally correct, but you can, of course, use things like ====== ${some [long] name} $some\ long \ name ====== But all it needs is a regexp pattern which does properly match all the valid ways to access a var through '''$''', and it should work like a charm - if anyone knows a more accurate value, please alter the code. It will also work on an infinite number of $'s. ====== rename proc overload_proc overload_proc proc {name args body} { while {[regexp {\$(\$+[[:alnum:]_]+)} $body]} { regsub -all {(\$(\$+[[:alnum:]_]+))} $body "\[set \\2\]" body } ::overload_proc $name $args $body } # and a small test proc foobar {} { set real yay! set p1 real set p2 p1 set p3 p2 puts "$real / $$p1 / $$$p2 / $$$$p3" } foobar;# prints "yay! / yay! / yay! / yay! ====== (Yup, it basically just edits ====== $$$foo ====== out to ====== [set [set $foo]] ====== which is the "real" way to do nested variables/dereferencing. Check `[info body] foobar` after running the code+demo above, if you want to see the result.) (Oh, that does also mean that if you have, for instance, ====== set myvar {some text we $$foo don't want evaled or edited} ====== you'll end up with ====== set myvar {some text we [set $foo] don't want evaled or edited} ====== which is wrong. But this is just a 2am piece of example code ;) <> Concept | Arts and crafts of Tcl-Tk programming