For Programmers: Free Programming Magazines  


Home > Archive > Tcl > October 2005 > Setting namespace variables









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Setting namespace variables
graeme.pietersz@gmail.com

2005-10-19, 3:57 am

Can someone please explain to me why this happens?

% set a 10
10
% namespace eval ::n1 {set b $a}
10
% set ::n1::b
10
% namespace eval ::n1 {set a $a}
10
% set ::n1::a
can't read "::n1::a": no such variable
% namespace eval ::n1 {set c 10}
10
% set ::n1::c
10
% namespace eval ::n1 {set a 10}
10
% set ::n1::a
can't read "::n1::a": no such variable
%

I had expected to have ::n1::a set to 10 (both times)

suchenwi

2005-10-19, 3:57 am

This is the namespace resolution problem - "Dangers of creative
writing", http://wiki.tcl.tk/1030 . The short answer is: use [variable]
to set or declare variables in namespaces - or full paths:

namespace eval n1 {variable foo 42}
or
set ::n1::foo 42

Note that variables in namespaces are global too, so the same drawbacks
apply. Use local variables wherever possible - it's safer and faster :)

graeme.pietersz@gmail.com schrieb:

> Can someone please explain to me why this happens?
>
> % set a 10
> 10


This sets a global variable (in namespace ::).

> % namespace eval ::n1 {set b $a}
> 10
> % set ::n1::b
> 10


This creates a variable in namespace n1.

> % namespace eval ::n1 {set a $a}
> 10


This finds there is a global "a", so it uses that...

> % set ::n1::a
> can't read "::n1::a": no such variable


....and does not create one in n1.

> % namespace eval ::n1 {set c 10}
> 10
> % set ::n1::c
> 10


Like "b" above.

> % namespace eval ::n1 {set a 10}
> 10
> % set ::n1::a
> can't read "::n1::a": no such variable
> %
>
> I had expected to have ::n1::a set to 10 (both times)


graeme.pietersz@gmail.com

2005-10-19, 7:59 am

suchenwi wrote:
> This is the namespace resolution problem - "Dangers of creative
> writing", http://wiki.tcl.tk/1030 . The short answer is: use [variable]
> to set or declare variables in namespaces - or full paths:


Thanks, that helped a lot. Between your explanation and the wiki link
(which I had completely failed to find although I did try!) I have (I
think) got it.

I will declare namespace variables in future.

>
> namespace eval n1 {variable foo 42}
> or
> set ::n1::foo 42
>
> Note that variables in namespaces are global too, so the same drawbacks
> apply. Use local variables wherever possible - it's safer and faster :)
>


I have been trying to think of a way to avoid using namespaces. The
problem I have is a proc calling another proc which calls another proc
etc and the last proc needs to read and set values in the first. Using
a namespace looked neater than passing all the values needed back and
forth or using upvar.

Ulrich Schöbel

2005-10-19, 7:59 am

Hi,

what about using an array, either a global or a namespaced one,
for this purpose? You only need to declare one variable and then
use the index as kind of a variable name.

Best regards

Ulrich


In article <1129713810.766036.248620@o13g2000cwo.googlegroups.com>,
"graeme.pietersz@gmail.com" <graeme.pietersz@gmail.com> writes:
>
> I have been trying to think of a way to avoid using namespaces. The
> problem I have is a proc calling another proc which calls another proc
> etc and the last proc needs to read and set values in the first. Using
> a namespace looked neater than passing all the values needed back and
> forth or using upvar.
>

Donald Arseneau

2005-10-19, 7:59 am

"graeme.pietersz@gmail.com" <graeme.pietersz@gmail.com> writes:

> I have been trying to think of a way to avoid using namespaces. The
> problem I have is a proc calling another proc which calls another proc
> etc and the last proc needs to read and set values in the first. Using
> a namespace looked neater than passing all the values needed back and
> forth or using upvar.


A namespace looks right for that.

Furthermore, you won't have accidental collisions with global variables
when you are in a proc.

--
Donald Arseneau asnd@triumf.ca
graeme.pietersz@gmail.com

2005-10-24, 7:57 am

There is a problem with doing what I was trying to do: if the proc
exits without deleting the namespace it is not cleaned up like local
variables are. So one can end up with variables from a previous run of
the proc still in existence (if you use the same namespace name) or a
memory leak (if you generate a new namespace name each time). It worked
but became quite messy (wrapping everything up in a catch and deleting
the namespace if there was an exception for example).

I decided to take the advice I got and attempt to only use local
variables. My eventual solution was to pass the absolute level of the
proc (from [info level]) to each proc it calls. This is then passed
down the line. Then each proc upvars what it needs and only what it
needs. This is probably an obvious approach to seasoned TCLers but was
not to me. I am sure this is an obvious to many people who read this,
but I think it worth mentioning for the benefit of others like me.

suchenwi

2005-10-24, 7:57 am

Local variables in procs are

- safer, because they are discarded once the proc is left, and can
cause no side-effects

- faster, because they are created in the bytecode stackframe and
addressed by integer pointer, instead of requiring hash-table lookup by
name

Of course, when you need side-effects, say for stateful objects, or run
in global scope (e.g. Tk bindings), you still need global or namespaced
variables. But in very many cases, intermediate variables are best when
local :)

Shaun Deacon

2005-10-24, 9:57 pm

That makes sense...thanks for the explanation.

regards,
Shaun

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com