Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

We don't know one millionth of one percent about anything.


devel / comp.lang.tcl / Namespace context separation problem

SubjectAuthor
* Namespace context separation problemLuc
`* Re: Namespace context separation problemRich
 `* Re: Namespace context separation problemLuc
  `* Re: Namespace context separation problemRich
   `* Re: Namespace context separation problemLuc
    `* Re: Namespace context separation problemRich
     `- Re: Namespace context separation problemet99

1
Namespace context separation problem

<20240124174757.1a828ba6@lud1.home>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=12845&group=comp.lang.tcl#12845

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: luc...@sep.invalid (Luc)
Newsgroups: comp.lang.tcl
Subject: Namespace context separation problem
Date: Wed, 24 Jan 2024 17:47:57 -0300
Organization: A noiseless patient Spider
Lines: 58
Message-ID: <20240124174757.1a828ba6@lud1.home>
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Injection-Info: dont-email.me; posting-host="22e8e93c12f018dde8ac46cf26717871";
logging-data="2062574"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/OWHxQcjEletLl44YGpI3NXUYP0dGHtrM="
Cancel-Lock: sha1:7Usg+wrSleCFjlC/qfs4iRVVx70=
 by: Luc - Wed, 24 Jan 2024 20:47 UTC

Hi. Here is the code:

------------------------
namespace eval AllWidgets {
namespace eval RightClickMenu {
set ::[namespace tail [namespace current]] [namespace current]
puts "set ::[namespace tail [namespace current]] [namespace current]"
}
} namespace eval CFG {
namespace eval WidgetConfig {}
}

namespace eval CFG::WidgetConfig {
set RightClickMenu {
-font "Freesans 16"
-background "#FFFFFF"
-foreground "#000000"
}
}

puts $CFG::WidgetConfig::RightClickMenu
------------------------

In the first namespace, AllWidgets, I create a child namespace named
RightClickMenu. In that child namespace, I create a global variable
named ::RightClickMenu.

I could probably just ditch that because it's a leftover of the old
design (I am rewriting and redesigning everything), but I really would
like to understand what is going on here.

Note that I put a 'puts' statement there to debug the effect of the
previous line. That previous line breaks the last line in the sample
code.

set ::RightClickMenu ::AllWidgets::RightClickMenu
can't read "CFG::WidgetConfig::RightClickMenu": no such variable
while executing
"puts $CFG::WidgetConfig::RightClickMenu"
(file "namespacetests.tcl" line 19)
Compilation failed.

The problem goes away if I delete that line that creates the global
variable.

I was very sure I would get the value of the variable RightClickMenu
that was created inside the WidgetConfig namespace which is a child of
the CFG namespace. To my dismay, it clashes with a global namesake, a
variable that exists in another scope.

Why?

--
Luc
>>

Re: Namespace context separation problem

<uos3cs$200hs$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=12848&group=comp.lang.tcl#12848

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!i2pn.org!news.hispagatos.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ric...@example.invalid (Rich)
Newsgroups: comp.lang.tcl
Subject: Re: Namespace context separation problem
Date: Wed, 24 Jan 2024 22:36:12 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 170
Message-ID: <uos3cs$200hs$1@dont-email.me>
References: <20240124174757.1a828ba6@lud1.home>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Injection-Date: Wed, 24 Jan 2024 22:36:12 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="2abe0e15a4d5b6beff2c38d1284ede0a";
logging-data="2097724"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18HATh9YXCAJHHjkuB6UVaP"
User-Agent: tin/2.6.1-20211226 ("Convalmore") (Linux/5.15.139 (x86_64))
Cancel-Lock: sha1:rXIcQSanG8rDHVR4S3d7Fky8bvQ=
 by: Rich - Wed, 24 Jan 2024 22:36 UTC

Luc <luc@sep.invalid> wrote:
> Hi. Here is the code:

Thanks, this is helpful, very helpful.

> ------------------------
> namespace eval AllWidgets {
> namespace eval RightClickMenu {
> set ::[namespace tail [namespace current]] [namespace current]
> puts "set ::[namespace tail [namespace current]] [namespace current]"
> }
> }
> namespace eval CFG {
> namespace eval WidgetConfig {}
> }
>
>
> puts $CFG::WidgetConfig::RightClickMenu
> ------------------------
>
> In the first namespace, AllWidgets, I create a child namespace named
> RightClickMenu. In that child namespace, I create a global variable
> named ::RightClickMenu.
>
> I could probably just ditch that because it's a leftover of the old
> design (I am rewriting and redesigning everything), but I really would
> like to understand what is going on here.

You are not paying full attention to the namespace name resolution
rules (set out in the namespace manual page):

NAME RESOLUTION
In general, all Tcl commands that take variable and command names sup‐
port qualified names. This means you can give qualified names to such
commands as set, proc, rename, and interp alias. If you provide a
fully-qualified name that starts with a ::, there is no question about
what command, variable, or namespace you mean. However, if the name
does not start with a :: (i.e., is relative), Tcl follows basic rules
for looking it up:

• Variable names are always resolved by looking first in the cur‐
rent namespace, and then in the global namespace.

Given your code, the "AllWidgets" does indeed set a global variable.
And it is a fully quailfied global, so none of the name resolution
rules come into play.

But, here (for the code you posted):

> namespace eval CFG::WidgetConfig {
> set RightClickMenu {
> -font "Freesans 16"
> -background "#FFFFFF"
> -foreground "#000000"
> }
> }

When this snippet is executed, CFG::WidgetConfig does not exist
(because none of the posted code created it before), so it contains no
variable names.

You then try to 'set' an unqualified variable name within the namespace
creation script. That invokes the name resolution rules. So what Tcl
does is:

1) looks in current namespace (i.e., CFG::WidgetConfig) for a variable
named "RightClickMenu" and finds the current namespace has no variable
in it of that name (remember, it is empty at this point). So it finds
nothing, and invokes the second half of the "variable name" look rule.

2) it now looks in the global namespace, and it finds "RightClickMenu"
as a global variable in the global namespace. So Tcl updates the value
stored in ::RightClickMenu for you.

You can see this effect if you run your code, one statement at a time,
from a REPL:

$ rlwrap tclsh
% namespace eval AllWidgets {
namespace eval RightClickMenu {
set ::[namespace tail [namespace current]] [namespace current]
puts "set ::[namespace tail [namespace current]] [namespace current]"
}
}
set ::RightClickMenu ::AllWidgets::RightClickMenu
% info globals
tcl_rcFileName tcl_version argv0 argv tcl_interactive RightClickMenu auto_path auto_index env tcl_pkgPath tcl_patchLevel argc tcl_library tcl_platform
% set ::RightClickMenu
::AllWidgets::RightClickMenu
% namespace eval CFG {
namespace eval WidgetConfig {}
}
% namespace eval CFG::WidgetConfig {
set RightClickMenu {
-font "Freesans 16"
-background "#FFFFFF"
-foreground "#000000"
}
}

-font "Freesans 16"
-background "#FFFFFF"
-foreground "#000000"

% puts $CFG::WidgetConfig::RightClickMenu
can't read "CFG::WidgetConfig::RightClickMenu": no such variable

Note I added in an 'info globals' and set ::RightClickMenu just to show
that the variable is now in the global namespace, and to show it's
contents, before running the last two statements.

Now, look what the contents of the global variable are, after the last
two statements:

% set ::RightClickMenu

-font "Freesans 16"
-background "#FFFFFF"
-foreground "#000000"

%

Presumably you want the namespace'ed RightClickMenu to be in that
namespace (implied by your puts of the fully qualified version). In
which case you need to first create the variable in the namespace,
which is the purpose of the "variable" command.

Watch:

$ rlwrap tclsh
% namespace eval AllWidgets {
namespace eval RightClickMenu {
set ::[namespace tail [namespace current]] [namespace current]
puts "set ::[namespace tail [namespace current]] [namespace current]"
}
}
set ::RightClickMenu ::AllWidgets::RightClickMenu
% set ::RightClickMenu
::AllWidgets::RightClickMenu
% namespace eval CFG {
namespace eval WidgetConfig {}
}
% namespace eval CFG::WidgetConfig {
variable RightClickMenu
set RightClickMenu {
-font "Freesans 16"
-background "#FFFFFF"
-foreground "#000000"
}
}

-font "Freesans 16"
-background "#FFFFFF"
-foreground "#000000"

% puts $CFG::WidgetConfig::RightClickMenu

-font "Freesans 16"
-background "#FFFFFF"
-foreground "#000000"

% set ::RightClickMenu
::AllWidgets::RightClickMenu
%

You first have to make the variable 'exist' in the namespace, which is
what the 'variable' command will do for you. Note that the global is
no longer modified in this changed bit of code.

Re: Namespace context separation problem

<20240124204656.6160d735@lud1.home>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=12850&group=comp.lang.tcl#12850

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!rocksolid2!news.neodome.net!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: luc...@sep.invalid (Luc)
Newsgroups: comp.lang.tcl
Subject: Re: Namespace context separation problem
Date: Wed, 24 Jan 2024 20:46:56 -0300
Organization: A noiseless patient Spider
Lines: 80
Message-ID: <20240124204656.6160d735@lud1.home>
References: <20240124174757.1a828ba6@lud1.home>
<uos3cs$200hs$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Injection-Info: dont-email.me; posting-host="a820b890d29bb4b14f22abf28b8f4e6c";
logging-data="2111216"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/JuZGqMnVNA0tI6OmA31aYSjDh4Ia2wp0="
Cancel-Lock: sha1:mO7VY2AAdbOmGQmB9JCBEd7XcaI=
 by: Luc - Wed, 24 Jan 2024 23:46 UTC

On Wed, 24 Jan 2024 22:36:12 -0000 (UTC), Rich wrote:

>You are not paying full attention to the namespace name resolution
>rules (set out in the namespace manual page):

Thanks, but you are confusing me for the first time. I really don't
understand this:

>> namespace eval CFG::WidgetConfig {
>> set RightClickMenu {
>> -font "Freesans 16"
>> -background "#FFFFFF"
>> -foreground "#000000"
>> }
>> }
>
>When this snippet is executed, CFG::WidgetConfig does not exist
>(because none of the posted code created it before), so it contains no
>variable names.

Yes, it does. First I create CFG:

namespace eval CFG {...

and right inside it I immediately create WidgetConfig:

namespace eval WidgetConfig {}

Only after that, I do namespace eval CFG::WidgetConfig {...
By the time I do that, yes, CFG::WidgetConfig does exist. It was
created immediately before. So you lost me there.

>You then try to 'set' an unqualified variable name within the namespace
>creation script. That invokes the name resolution rules. So what Tcl
>does is:
>
>1) looks in current namespace (i.e., CFG::WidgetConfig) for a variable
>named "RightClickMenu" and finds the current namespace has no variable
>in it of that name (remember, it is empty at this point). So it finds
>nothing, and invokes the second half of the "variable name" look rule.

Unqualified? It finds nothing? That requirement is news to me. I assume
the 'set' command has enough authority to officialize the creation and
qualification of the new variable in Tcl's internal notary office.
Manual:

"If value is specified, then set the value of varName to value, creating
a new variable if one does not already exist, ..."

>2) it now looks in the global namespace, and it finds "RightClickMenu"
>as a global variable in the global namespace. So Tcl updates the value
>stored in ::RightClickMenu for you.

Your words make sense, but the language's behavior doesn't. I absolutely
assumed that being inside a namespace would make everything belong to
that namespace by default. If Tcl prefers a global variable to a "local"
variable in a command that takes place inside a namespace, I feel
betrayed. I don't feel so safe coding inside a namespace anymore.

>You first have to make the variable 'exist' in the namespace, which is
>what the 'variable' command will do for you. Note that the global is
>no longer modified in this changed bit of code.

The rest of your explanation is very thoughtful, but I still find it
hard to understand or maybe just hard to *accept* that I need to use
'variable' because 'set' won't do the job in spite of their having such
(nearly?) identical descriptions in the manual. I just think that the
'variable' command is unwarranted and weird.

Thank you.

--
Luc
>>

Re: Namespace context separation problem

<uoscub$217dd$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=12851&group=comp.lang.tcl#12851

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!rocksolid2!news.neodome.net!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ric...@example.invalid (Rich)
Newsgroups: comp.lang.tcl
Subject: Re: Namespace context separation problem
Date: Thu, 25 Jan 2024 01:19:07 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 140
Message-ID: <uoscub$217dd$1@dont-email.me>
References: <20240124174757.1a828ba6@lud1.home> <uos3cs$200hs$1@dont-email.me> <20240124204656.6160d735@lud1.home>
Injection-Date: Thu, 25 Jan 2024 01:19:07 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="544391276f46615823713a66bb29ff30";
logging-data="2137517"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+NjF0qqvDvLK0xFtOxC1dM"
User-Agent: tin/2.6.1-20211226 ("Convalmore") (Linux/5.15.139 (x86_64))
Cancel-Lock: sha1:8Ej8pZGc9DH0bZl2mhi9Kdepj3Q=
 by: Rich - Thu, 25 Jan 2024 01:19 UTC

Luc <luc@sep.invalid> wrote:
> On Wed, 24 Jan 2024 22:36:12 -0000 (UTC), Rich wrote:
>
>>You are not paying full attention to the namespace name resolution
>>rules (set out in the namespace manual page):
>
> Thanks, but you are confusing me for the first time. I really don't
> understand this:
>
>
>>> namespace eval CFG::WidgetConfig {
>>> set RightClickMenu {
>>> -font "Freesans 16"
>>> -background "#FFFFFF"
>>> -foreground "#000000"
>>> }
>>> }
>>
>>When this snippet is executed, CFG::WidgetConfig does not exist
>>(because none of the posted code created it before), so it contains no
>>variable names.
>
> Yes, it does. First I create CFG:

Fair enough, when I wrote that I overlooked that you'd created it in
the prior statement. But it is also still empty even at that time.

> namespace eval CFG {...
>
> and right inside it I immediately create WidgetConfig:
>
> namespace eval WidgetConfig {}
>
> Only after that, I do namespace eval CFG::WidgetConfig {...
> By the time I do that, yes, CFG::WidgetConfig does exist. It was
> created immediately before. So you lost me there.
>
>
>>You then try to 'set' an unqualified variable name within the namespace
>>creation script. That invokes the name resolution rules. So what Tcl
>>does is:
>>
>>1) looks in current namespace (i.e., CFG::WidgetConfig) for a variable
>>named "RightClickMenu" and finds the current namespace has no variable
>>in it of that name (remember, it is empty at this point). So it finds
>>nothing, and invokes the second half of the "variable name" look rule.
>
> Unqualified?

Unqualified means without any :: in the name

Unqualified: varname

Qualified: varname::somevar

Fully qualified: ::varname::somevar

> It finds nothing?

Just before the "set" begings to be executed, there are no variables in
that namespace (because you had not yet created any there).

As the "set" is in the process of being executed, it first has to
decide what final end variable will be the target. Because the name in
the set command has no :: anywhere, and no leading ::, it is
'unqualifieed', which triggers the "name resolution rules". Since the
namespace is still empty (the set has not created any variables, as it
is in the process of being interpreted) the name resolution rules do
not find an existing namespace variable already present. Which
triggers the "look in the global namespace" rule, an it finds one
there. So Tcl picks the gloabl as the intended target, and uses it.

> That requirement is news to me.

Read the namespace manual page.

> I assume the 'set' command has enough authority to officialize the
> creation and qualification of the new variable in Tcl's internal
> notary office. Manual:

Modified by the namespace "name resolution" rules. That's what's
messing you up.

> "If value is specified, then set the value of varName to value, creating
> a new variable if one does not already exist, ..."

None of the above senteence defines "where" the end result will reside.
The namespace name resolution rules are the "decide where" (as in what
namespace) the name will refer.

>>2) it now looks in the global namespace, and it finds "RightClickMenu"
>>as a global variable in the global namespace. So Tcl updates the value
>>stored in ::RightClickMenu for you.
>
> Your words make sense, but the language's behavior doesn't. I
> absolutely assumed that being inside a namespace would make
> everything belong to that namespace by default.

Unfortunately not, that's a quirk of namespaces. Just doing 'set'
inside one does not create variables in that namespace.

> If Tcl prefers a global variable to a "local" variable in a command
> that takes place inside a namespace, I feel betrayed. I don't feel
> so safe coding inside a namespace anymore.

It is a complete non-issue if you use "variable" to first create them
(which also acts as documentation of their existance) and/or initialize
them (variable can both create, and give a value to, the new variable
name).

>>You first have to make the variable 'exist' in the namespace, which is
>>what the 'variable' command will do for you. Note that the global is
>>no longer modified in this changed bit of code.
>
> The rest of your explanation is very thoughtful, but I still find it
> hard to understand or maybe just hard to *accept* that I need to use
> 'variable' because 'set' won't do the job in spite of their having such
> (nearly?) identical descriptions in the manual. I just think that the
> 'variable' command is unwarranted and weird.

The part of the 'set' man page you overlooked is this one:

If varName includes namespace qualifiers (in the array name if it
refers to an array element), or if varName is unqualified (does not
include the names of any containing namespaces) but no procedure is
active, varName refers to a namespace variable resolved according
to the rules described under NAME RESOLUTION in the namespace
manual page.

When you run 'set' inside a namespace eval, you have "no active
procedure", and when the variable name is 'unqualified" (no ::
anywhere), you get the name resolution rules defined for namespaces.
Which produces this somewhat unexpected result until one connects the
dots between the name resolution rules and set's behavior.

The reason you don't notice the effect unless inside a namespace eval
is because when you are otherwise outside of a procedure you are
already in the global namespace, so no matter how the name is resolved,
it ends up in the global namespace.

Re: Namespace context separation problem

<20240125003310.35a77b03@lud1.home>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=12852&group=comp.lang.tcl#12852

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!i2pn.org!news.chmurka.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: luc...@sep.invalid (Luc)
Newsgroups: comp.lang.tcl
Subject: Re: Namespace context separation problem
Date: Thu, 25 Jan 2024 00:33:10 -0300
Organization: A noiseless patient Spider
Lines: 25
Message-ID: <20240125003310.35a77b03@lud1.home>
References: <20240124174757.1a828ba6@lud1.home>
<uos3cs$200hs$1@dont-email.me>
<20240124204656.6160d735@lud1.home>
<uoscub$217dd$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Injection-Info: dont-email.me; posting-host="a820b890d29bb4b14f22abf28b8f4e6c";
logging-data="2291667"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18q1pBKCACU7BIbU7NNWQpAfIXhr5dVgZc="
Cancel-Lock: sha1:mhRlt/55/lOjyCk+bAki1vXNU4s=
 by: Luc - Thu, 25 Jan 2024 03:33 UTC

On Thu, 25 Jan 2024 01:19:07 -0000 (UTC), Rich wrote:

>It is a complete non-issue if you use "variable" to first create them
>(which also acts as documentation of their existance) and/or initialize
>them (variable can both create, and give a value to, the new variable
>name).

This is all beginning to settle down in my head and I think I understand
it now. I just don't like it. I don't like it. If I am coding inside a
namespace, I think the context of the namespace has to prevail.

It's rare for me to dislike something about Tcl but well, it happens.

And I've been coding some more here and guess what, I'm using 'variable'
instead of 'set' all over the place now. I don't trust 'set' anymore.
At least in namespaces no, I don't, I will probably never use 'set'
inside a namespace again.

Thank you.

--
Luc
>>

Re: Namespace context separation problem

<uoso33$26a8l$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=12853&group=comp.lang.tcl#12853

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!rocksolid2!news.neodome.net!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ric...@example.invalid (Rich)
Newsgroups: comp.lang.tcl
Subject: Re: Namespace context separation problem
Date: Thu, 25 Jan 2024 04:29:23 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 86
Message-ID: <uoso33$26a8l$1@dont-email.me>
References: <20240124174757.1a828ba6@lud1.home> <uos3cs$200hs$1@dont-email.me> <20240124204656.6160d735@lud1.home> <uoscub$217dd$1@dont-email.me> <20240125003310.35a77b03@lud1.home>
Injection-Date: Thu, 25 Jan 2024 04:29:23 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="544391276f46615823713a66bb29ff30";
logging-data="2304277"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18lBPdsj0d3Ds9bDM9jxtwi"
User-Agent: tin/2.6.1-20211226 ("Convalmore") (Linux/5.15.139 (x86_64))
Cancel-Lock: sha1:js2TxQ2QmDLc3v4PIyGvXouQAhs=
 by: Rich - Thu, 25 Jan 2024 04:29 UTC

Luc <luc@sep.invalid> wrote:
> On Thu, 25 Jan 2024 01:19:07 -0000 (UTC), Rich wrote:
>
>>It is a complete non-issue if you use "variable" to first create them
>>(which also acts as documentation of their existance) and/or initialize
>>them (variable can both create, and give a value to, the new variable
>>name).
>
> This is all beginning to settle down in my head and I think I understand
> it now. I just don't like it. I don't like it. If I am coding inside a
> namespace, I think the context of the namespace has to prevail.
>
> It's rare for me to dislike something about Tcl but well, it happens.
>
> And I've been coding some more here and guess what, I'm using 'variable'
> instead of 'set' all over the place now. I don't trust 'set' anymore.
> At least in namespaces no, I don't, I will probably never use 'set'
> inside a namespace again.

That's for the best, the name resolution rules make set, in a namespace
but outside a proc, a bit of a footgun.

Also note that 'variable' is useful for using namespace variables
inside of procs as storage that outlives the proc's execution.

I.e.:

---code---
namespace eval ::example {
variable yy 42

proc printyy {} {
variable yy
puts "yy is '$yy'"
}

proc changeyy {value} {
variable yy
set yy $value
}
}

puts [info globals]

puts "First printyy"
example::printyy

puts "Calling changeyy"
example::changeyy hello

puts "Second printyy"
example::printyy
--end code---

Running this results in:

tcl_rcFileName tcl_version argv0 argv tcl_interactive auto_path env tcl_pkgPath tcl_patchLevel argc tcl_library tcl_platform
First printyy
yy is '42'
Calling changeyy
Second printyy
yy is 'hello'

Or, another useful use, a 'counter' that remembers its last value:

$ rlwrap tclsh
% namespace eval ::counter {
variable count

proc get {} {
variable count
return [incr count]
}
}
% counter::get
1
% counter::get
2
% counter::get
3
% counter::get
4
%

This last use (the counter) is for all intents, a 'self made object'.

Re: Namespace context separation problem

<uoui9p$2f81n$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=12855&group=comp.lang.tcl#12855

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!rocksolid2!news.neodome.net!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: et9...@rocketship1.me (et99)
Newsgroups: comp.lang.tcl
Subject: Re: Namespace context separation problem
Date: Thu, 25 Jan 2024 13:02:47 -0800
Organization: A noiseless patient Spider
Lines: 110
Message-ID: <uoui9p$2f81n$1@dont-email.me>
References: <20240124174757.1a828ba6@lud1.home> <uos3cs$200hs$1@dont-email.me>
<20240124204656.6160d735@lud1.home> <uoscub$217dd$1@dont-email.me>
<20240125003310.35a77b03@lud1.home> <uoso33$26a8l$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Thu, 25 Jan 2024 21:02:49 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="c76d74943cc44efbb9b31af573c92e1c";
logging-data="2596919"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19tLD8Yo/+jG7gdv4/8NCCj"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.6.1
Cancel-Lock: sha1:sAqoTqbms5BkvtOaCXhlDy/azR0=
In-Reply-To: <uoso33$26a8l$1@dont-email.me>
Content-Language: en-US
 by: et99 - Thu, 25 Jan 2024 21:02 UTC

On 1/24/2024 8:29 PM, Rich wrote:
> Luc <luc@sep.invalid> wrote:
>> On Thu, 25 Jan 2024 01:19:07 -0000 (UTC), Rich wrote:
>>
>>> It is a complete non-issue if you use "variable" to first create them
>>> (which also acts as documentation of their existance) and/or initialize
>>> them (variable can both create, and give a value to, the new variable
>>> name).
>>
>> This is all beginning to settle down in my head and I think I understand
>> it now. I just don't like it. I don't like it. If I am coding inside a
>> namespace, I think the context of the namespace has to prevail.
>>
>> It's rare for me to dislike something about Tcl but well, it happens.
>>
>> And I've been coding some more here and guess what, I'm using 'variable'
>> instead of 'set' all over the place now. I don't trust 'set' anymore.
>> At least in namespaces no, I don't, I will probably never use 'set'
>> inside a namespace again.
>
> That's for the best, the name resolution rules make set, in a namespace
> but outside a proc, a bit of a footgun.
>
>
> Also note that 'variable' is useful for using namespace variables
> inside of procs as storage that outlives the proc's execution.
>
> I.e.:
>
> ---code---
> namespace eval ::example {
> variable yy 42
>
> proc printyy {} {
> variable yy
> puts "yy is '$yy'"
> }
>
> proc changeyy {value} {
> variable yy
> set yy $value
> }
> }
>
> puts [info globals]
>
> puts "First printyy"
> example::printyy
>
> puts "Calling changeyy"
> example::changeyy hello
>
> puts "Second printyy"
> example::printyy
> --end code---
>
> Running this results in:
>
> tcl_rcFileName tcl_version argv0 argv tcl_interactive auto_path env tcl_pkgPath tcl_patchLevel argc tcl_library tcl_platform
> First printyy
> yy is '42'
> Calling changeyy
> Second printyy
> yy is 'hello'
>
> Or, another useful use, a 'counter' that remembers its last value:
>
> $ rlwrap tclsh
> % namespace eval ::counter {
> variable count
>
> proc get {} {
> variable count
> return [incr count]
> }
> }
> % counter::get
> 1
> % counter::get
> 2
> % counter::get
> 3
> % counter::get
> 4
> %
>
> This last use (the counter) is for all intents, a 'self made object'.

Note that Luc's example in his first post does not error out in tcl 9.0b1. That is one of the incompatible changes that were made.

Other code that needs to change is the use of non-fully qualified uses of global variables such as tcl_platform, which before tcl 9 would refer to the global variable, but not any longer, when inside a namespace eval.

(bin) 1 % namespace eval foo {parray tcl_platform}
"tcl_platform" isn't an array
(bin) 2 % namespace eval foo {parray ::tcl_platform}
::tcl_platform(byteOrder) = littleEndian
::tcl_platform(engine) = Tcl
::tcl_platform(machine) = amd64
::tcl_platform(os) = Windows NT
::tcl_platform(osVersion) = 10.0
::tcl_platform(pathSeparator) = ;
::tcl_platform(platform) = windows
::tcl_platform(pointerSize) = 8
::tcl_platform(user) = core5
::tcl_platform(wordSize) = 4
(bin) 3 % info pa
9.0b1

1
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor