Version 8 of how do i do $$var - double dereferencing a variable

Updated 2003-04-16 12:32:28

This issue of dereferencing seems to come up frequently enough to deserve a page of tips, suggestions, warnings, etc. Tcl is documented to, and does, work as follows:

 % set amount 42
 42
 % puts "I owe you $$amount"
 I owe you $42

The first dollar sign cannot be parsed as variable reference, and is left as is; the second resolves with $amount.

The basic situation is that a user is trying, either intentionally or accidentally, to do pointer like design.

So they end up discovering they need to do something like:

 set a "123"
 set b "3.1415"
 set c "The price of petrol in Peroria"

 foreach var {a b c} {
   puts [set $var]
 }

DKF: More often than not, a solution involving arrays produces a better (more robust, etc.) result:

 set data(a) "123"
 set data(b) "3.1415"
 set data(c) "The price of petrol in Peroria"

 foreach var {a b c} {
    puts $data($var)
 }

Another possibility (more so when splitting things up into procedures) is to use upvar.


TV It's probably worth a page by itself as a subject. A pointer in C language sense is not the same as a indirect reference. Also, associations are not the same as referencing something by name and that is not the same as a pointer in C, in normal language or in for instance a URL. And a function, as clearly the case in tcl is referenced by name, and can be stored as a list.

The simple answer I guess is to use eval:

 set whichvar b
 set b 11
 eval puts $$whichvar

Which leaves a lot of questions about quoting, and preventing the evaluator to perform substitutions (possible through escaping).

A pointer in C, which is rarely seriously usefull in large repetition as in ****something, that would refer to datastructures and referencing them which can work for initializing accessing something in a tree when the structure contains the forward reference as first element, is not the same idea. A pointer in a digital signal processor could be pointing in a subspace of memory not made into the comfortable the_whole_memory_is_one_linear_list which also PC hearts eventually got around to (more or less..), which is like in computer design, where something is a pointer when it is used to point into a memory, which is just the same as an integer memory with access to some address bus.

Though of course in C one would refer to another variable through a pointer, which in various senses is also a variable:

 main()
 {
    int i;
    int *pointer;

     i = 13;
     pointer = &i
     *pointer = 14;
     return *pointer;

}

In Tcl, we have symbolic behaviour of the tcl interpreter which of course at some level and point are implemented at C level (I think it all it, though I could be mistaking) which makes variable referencing by name in runtime different than the above C level.

A nice example is:

 info var prefix_*

which lists all the variables with a certain prefix.

I just tried to list some functions associated with blocks on the bwise canvas:

 (Tcl) 101 % foreach var [info var *bfunc] {eval puts \"$var $\{$var\}\"}
 mapping.bfunc:  set mapping.newstate [fsm_state_map ${mapping.oldstate} ${mapping.input} ] ;   set mapping.output [fsm_output_map ${mapping.oldstate} ${mapping.input} ] 
 Entry1.bfunc: 
 Proc1.bfunc:  set Proc1.out ${Proc1.in} 
 state.bfunc:  set state.out ${state.in} 
 Mon1.bfunc: .mw.c.mon1 del 0.0 end ;.mw.c.mon1 insert end "${Mon1.in} \n" ; .mw.c.mon1 see end

The messy looking (though I'm used to it) string like construction is for the aforementioned quoting and substitution issue. Variable names are considered to end with a dot (.) so I have to enclose them in braces to make them a list first.

Referencing commands through variables, and making that a programming habit has the clear risc that one may loose touch of what happens, but then again, using certain strings with the system command containing those wonderfull Recursive options can be dangerous just the same. And it is not illegal in computers to do symbolic referencing, its just not common practice, because direct and relatively fast indirect referencing as we know it in C and other compiled (fast and formal) languages is based on numerical representation of uniquely defined memory locations containing the referenced data. A pointer is usually even literally an integer, though it is possible to have bit shift and obviously ranges involved.

To make one variable reference another, one would need to first resolve the name of the target variable to the memory location where it resides, by using an associative procedure, assuming such is possible, as it is with what we consider ordinary computers.

In tcl, referencing to a variable can be resolved in runtime with no special effort, and quite efficiently, and the syntax at least does not prevent one to use above kind of constuctions elaborately. The constructs themselves are not something computer science shouldn't be into, it was the stuff which also was in the so manieth generation computers (I think it was 5th) which was in attention a few decades ago.

Certain problems, which are nowadays often seen as to be solved by a database (which of course will often in fact be also nothing much more but another C program with extensive associativeness and a large swapping memory pool, often not used all too efficiently compated to specific and well made solutions), are associative in nature, and of language is a good example. How we could use good formalisms to prevent errors and 'cover' a good spanning set of facilities and constructs is an interesting question in my opinion.


Category Tutorial