user1402185
user1402185

Reputation: 41

How can I output a list of the values for all variables from the info globals command?

I am trying to write a small bit of code that will list all of the variables and the values they contain in the info globals command. I have tried several iterations of substitution but cant get Tcl to treat the variable name as a variable, and return its value. Below is what I started with:

set fileid [open "c:/tcl variables.txt" w+]
foreach {x}  [lsort [info globals]]  {
    set y $x
    puts $fileid "$x  $y   "
}

I can get

DEG2RAD  DEG2RAD   
PI  PI   
RAD2DEG  RAD2DEG   
.....

or

DEG2RAD  $DEG2RAD   
PI  $PI   
RAD2DEG  $RAD2DEG   
.....

but what I need is

DEG2RAD  0.017453292519943295   
PI  3.1415926535897931   
RAD2DEG  57.295779513082323   
....   

Upvotes: 4

Views: 10148

Answers (3)

Tiberius371
Tiberius371

Reputation: 31

Arrays are variables too so just for reference, this outputs all variables (including arrays):

proc ListAllGlobals {{?pattern? *}} {
    foreach {name} [lsort [info globals ${?pattern?}]] {
        upvar {#0} $name var
        if {[array exists var]} {
            foreach {key val} [array get var] {
                puts "${name}($key) [list $val]"
            }
        } else {
            puts "$name [list $var]"
        }
    }
}
ListAllGlobals
ListAllGlobals tcl_platform
  1. I'm using list to enhanced readability of the values.
  2. A pattern can be specified for a subset of variables. It doesn't apply to array element names.
  3. In keeping with previous examples the output can be written to an opened file with: puts $fileid [ListAllGlobals]

Upvotes: 3

Donal Fellows
Donal Fellows

Reputation: 137567

The easiest method for doing this (because it avoids littering the output with your temporary variables) is to use a helper procedure and the upvar command:

proc listAllGlobals {filename} {
    set fileid [open $filename w+]
    foreach varname [lsort [info globals]] {
        upvar "#0" $varname var
        if {[array exists var]} continue;    # Skip global arrays...
        puts $fileid "$varname $var "
    }
    close $fileid
}
listAllGlobals "C:/tcl variables.txt"

If you've got Tcl 8.5, you can do this without creating a procedure:

apply {{} {
    set fileid [open "C:/tcl variables.txt" w+]
    foreach varname [lsort [info globals]] {
        upvar "#0" $varname var
        if {[array exists var]} continue;    # Skip global arrays...
        puts $fileid "$varname $var "
    }
    close $fileid
}}

This all works because what upvar does is link a local variable to a variable in another stack frame; #0 is the name of the global stack frame, $varname is the name of the variable in that context, and var is the local variable to bind to.

Upvotes: 4

ramanman
ramanman

Reputation: 873

I think you are looking for the subst command:

set fileid [open "c:/tcl variables.txt" w+] 
foreach {x} [lsort [info globals]] {
  puts $fileid "$x [subst $$x] " 
}

Alternatively, you can take advantage of the fact that set returns the value being set:

set fileid [open "c:/tcl variables.txt" w+] 
foreach {x} [lsort [info globals]] {
  puts $fileid "$x [set $x] " 
}

Upvotes: 7

Related Questions