Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

print all global variable values

831 views
Skip to first unread message

Patrick

unread,
Sep 30, 2009, 10:46:54 AM9/30/09
to
I am trying to do something that seemed so simple when I decided to do
it but I am still struggling with it. I am trying to print all global
variables and their values at a certain point in execution.

Here's what I have:

proc print_globals {} {
foreach name [info globals] {
global $name
puts "$name -> $$name"
}
}

the output of which I am trying to get to be
...
tcl_version -> 8.5
...

but here's what's actually occurring

tcl_version -> $tcl_version

I know I am overlooking something simple. A little help??

David Bariod

unread,
Sep 30, 2009, 10:52:31 AM9/30/09
to
On Sep 30, 4:46 pm, Patrick <patrick.dunni...@activecompliance.com>
wrote:

> I am trying to do something that seemed so simple when I decided to do
> it but I am still struggling with it. I am trying to print all global
> variables and their values at a certain point in execution.
>
> Here's what I have:
>
> proc print_globals {} {
> foreach name [info globals] {
> global $name
> puts "$name -> $$name"
> }
>
> }
>

The $variable_name is a short cut for
set variable_name
Two consecutive $ does not work.
You shoud use:
puts "$name -> [set $name]"
which is completely equivalent to
puts "[set name] -> [set [set name]]"

David Bariod

Patrick

unread,
Sep 30, 2009, 11:08:08 AM9/30/09
to
Perfect. Thanks. Here's the resulting procedure that I am using for
future reference:

proc print_globals {} {
foreach name [info globals] {
global $name

if [array exists $name] {
parray $name
} else {
puts "$name = [set $name]"
}
}
}

Bezoar

unread,
Oct 3, 2009, 6:59:16 PM10/3/09
to
On Sep 30, 10:08 am, Patrick <patrick.dunni...@activecompliance.com>
wrote:

this would also work

eval puts \"$name = \$$name\"

Carl

Jonathan Bromley

unread,
Oct 4, 2009, 10:54:47 PM10/4/09
to
On Sep 30, 10:08 am, Patrick wrote:

> proc print_globals {} {
> foreach name [info globals] {
>    global $name
>   if [array exists $name] {
>     parray $name
>    } else {
>      puts "$name = [set $name]"
>    }
> }
> }

The [upvar] command neatly combines making a global
reference with providing a convenient local alias.

proc print_globals {{pattern *}} {
foreach name [info globals $pattern] {
upvar #0 $name v
if {[array exists v]} {
parray v
} else {
puts "$name = $v"
}
}
}

This also could very easily be modified to
print variables in the calling, rather than the
global, scope (just use "upvar 1" instead of
"upvar #0"). Finally, the use of a match-pattern
that defaults to "*" gives a better parallel with
the behaviour of "info vars" and "info global".

hth
--
Jonathan Bromley

David Bariod

unread,
Oct 6, 2009, 10:03:01 AM10/6/09
to
On Oct 4, 12:59 am, Bezoar <cwjo...@gmail.com> wrote:
>
> this would also work
>
> eval puts \"$name = \$$name\"

This will not always work.
If your variable name contains space, it will fail.
Of course that is not a common usage to have space in
variable name but it is totally legal.

David Bariod

Donal K. Fellows

unread,
Oct 6, 2009, 12:38:31 PM10/6/09
to
On 30 Sep, 15:46, Patrick <patrick.dunni...@activecompliance.com>
wrote:

> I am trying to do something that seemed so simple when I decided to do
> it but I am still struggling with it. I am trying to print all global
> variables and their values at a certain point in execution.
>
> Here's what I have:
>
> proc print_globals {} {
>         foreach name [info globals] {
>                 global $name
>                 puts "$name -> $$name"
>         }
> }

That will go badly wrong if you have any global variables called
'name', you know? Try this one instead:

proc printGlobals {} {
foreach name [info globals] {
upvar #0 $name var
if {![info exist var]} continue; # Skip some awkward cases
if {[array exists var]} {
# This is a bit of cheat for printing an array...
uplevel #0 [list parray $name]
} else {
puts "$name -> $var"
}
}
}

Works when I try it (but produces rather more output than I care to
list here...)

> I know I am overlooking something simple. A little help??

Your problem was that $$ does not do double-dereferencing. You could
have tried with [set $name] instead, but that is still not as good as
the alternative I posted.

Donal.

tom.rmadilo

unread,
Oct 7, 2009, 5:13:46 PM10/7/09
to
On Oct 6, 9:38 am, "Donal K. Fellows"
<donal.k.fell...@manchester.ac.uk> wrote:

>           upvar #0 $name var
>           if {![info exist var]} continue;   # Skip some awkwar

Hmmm, so there are cases where globals show up in [info globals] but
don't yet have a value? I know this is the case with namespaced
variables, but couldn't reproduce with the equivalent [global myvar]
command.

Anyway, good to know.

Here's what I use in my "inspect" (code browser) package:

proc ::quotehtml { html } {
return [string map {< &lt; > &gt; & &amp;} $html]
}

proc ::inspect::findVars { namespace {pattern *}} {
return [lsort [info vars ${namespace}::$pattern]]
}

proc ::inspect::displayVars { {namespace ::} {pattern *} } {

set vars [::inspect::findVars $namespace $pattern]
set output "

<h4> Variables in $namespace</h4>
<pre>
"

foreach var $vars {
if {[array exists $var]} {
set arrayNames [array names $var]
append output "Array [quotehtml $var]\n"
foreach arrayName $arrayNames {
append output " [quotehtml ${var}\($arrayName\)] =
'[quotehtml [set ${var}($arrayName)]]'\n"
}
} elseif {[info exists $var]} {
append output " [quotehtml $var] = '[quotehtml [set $var]]'\n"
} else {
append output " [quotehtml $var] is currently undefined\n"
}
}

append output "</pre>\n"

return $output
}

By default this works on the global namespace and avoids the use of
[upvar].

Donal K. Fellows

unread,
Oct 8, 2009, 8:24:57 AM10/8/09
to
On 7 Oct, 22:13, "tom.rmadilo" <tom.rmad...@gmail.com> wrote:
> Hmmm, so there are cases where globals show up in [info globals] but
> don't yet have a value? I know this is the case with namespaced
> variables, but couldn't reproduce with the equivalent [global myvar]
> command.

Yes, when there are traces attached to an unset global variable (or
you've done certain very ugly things with [upvar]). This results in
the variable having an entry in the table of variables, but still
being marked as 'not existing'.

Donal.

0 new messages