You are viewing a plain text version of this content. The canonical link for it is here.
Posted to rivet-dev@tcl.apache.org by Damon Courtney <da...@your.unreality.com> on 2002/03/14 22:07:34 UTC

Global

Ok,

    I've been thinking about this a bit, and I'm thinking we should
really rename the global command on the global level.  IE: Instead of just
defining a global proc within the ::request namespace, we should define
that same proc in the :: namespace and make server-wide.

    My problem is this.  Everytime I write a proc of some kind to go in
the server, I have to upvar into the ::request namespace in order to keep
the variables localized.  Here's what I propose:

rename global trueGlobal

    And then, add an option to the global proc that says if the first
argument is "-true," it executes the true global command instead of
using the namespace.  Something like that anyway.

D


---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org


Re: Global

Posted by "David N. Welton" <da...@dedasys.com>.
Damon Courtney <da...@your.unreality.com> writes:

>     I'll give you a better example.  I ran into this while
> developing a project the other day, and I had to completely re-write
> the way I was doing things because of this limitation.

>     I create a namespace for my procedures.  I plan to put in a
> really slick packaging system for Rivet with each package in its own
> namespace.  So, we have:

> namespace eval ::some_package {

> }

>     See a problem?  Most packages create themselves relative to the
> global namespace.  This will become a problem when they use
> variables within their namespace.  Why?  Because that namespace will
> never be destroyed with the rest.  So, the next time a page loads,
> variables already exist that are from last time.  Bad juju.

>     Now, if we make the global command OUR global command, we just
> write all packages with global's instead of variable's, and it

So, we would have to rewrite packages to work with Rivet?

The ultimate goal is to make sure that people can take Tcl code and
"just use it" - or at least I think that's what we should aim for.

> ensures that all variables are kept within the ::request namespace.
> Very rarely should there ever be a case when a user needs the REAL
> global command.  And even if they did, 'upvar #0' works as a nice
> substitute. 0-]

-- 
David N. Welton
   Consulting: http://www.dedasys.com/
     Personal: http://www.dedasys.com/davidw/
Free Software: http://www.dedasys.com/freesoftware/
   Apache Tcl: http://tcl.apache.org/

---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org


Re: Global

Posted by Damon Courtney <da...@your.unreality.com>.
> Damon Courtney <da...@your.unreality.com> writes:
> 
> >     The commands I'm using aren't written in the ::request
> > namespace.  We don't want to have to reload all of Rivet's commands
> > everytime a request comes in, so we create the procs in the global
> > namespace.  But, occassionally, I want to load global variables, and
> > they actually do get loaded in stack #0.  Then, when ::request is
> > destroyed, they still hang around, and can cause really spurious
> > errors later on.
> 
> My original thinking with that bit of code was this:
> 
> I wanted to be able to run Tcl scripts with as little changes as
> possible in mod_dtcl, and 'global' was obviously causing some
> problems.  "variable" actually makes more sense, but that requires
> modification of the script.
> 
> It's possible, of course, to just use ::global, as that's still the
> real thing.
> 
> And, to discuss the earlier comment... hrm, instead of upvar'ing,
> wouldn't it be more explicit to just refer to ::request::foo ?

    I'll give you a better example.  I ran into this while developing
a project the other day, and I had to completely re-write the way I was
doing things because of this limitation.

    I create a namespace for my procedures.  I plan to put in a really
slick packaging system for Rivet with each package in its own namespace.
So, we have:

namespace eval ::some_package {

}

    See a problem?  Most packages create themselves relative to the
global namespace.  This will become a problem when they use variables
within their namespace.  Why?  Because that namespace will never be
destroyed with the rest.  So, the next time a page loads, variables
already exist that are from last time.  Bad juju.

    Now, if we make the global command OUR global command, we just write
all packages with global's instead of variable's, and it ensures that all
variables are kept within the ::request namespace.  Very rarely should
there ever be a case when a user needs the REAL global command.  And even
if they did, 'upvar #0' works as a nice substitute. 0-]

D


---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org


Re: Global

Posted by "David N. Welton" <da...@dedasys.com>.
Damon Courtney <da...@your.unreality.com> writes:

>     The commands I'm using aren't written in the ::request
> namespace.  We don't want to have to reload all of Rivet's commands
> everytime a request comes in, so we create the procs in the global
> namespace.  But, occassionally, I want to load global variables, and
> they actually do get loaded in stack #0.  Then, when ::request is
> destroyed, they still hang around, and can cause really spurious
> errors later on.

My original thinking with that bit of code was this:

I wanted to be able to run Tcl scripts with as little changes as
possible in mod_dtcl, and 'global' was obviously causing some
problems.  "variable" actually makes more sense, but that requires
modification of the script.

It's possible, of course, to just use ::global, as that's still the
real thing.

And, to discuss the earlier comment... hrm, instead of upvar'ing,
wouldn't it be more explicit to just refer to ::request::foo ?

-- 
David N. Welton
   Consulting: http://www.dedasys.com/
     Personal: http://www.dedasys.com/davidw/
Free Software: http://www.dedasys.com/freesoftware/
   Apache Tcl: http://tcl.apache.org/

---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org


Re: Global

Posted by Wojciech Kocjan <wo...@kocjan.org>.
Damon Courtney wrote:
>     Oh, I know the variable command well.  I do most of my programming
> in namespaces to avoid collusion, but that doesn't help me here.  The
> commands I'm creating are in the global namespace.  If I use the variable
> command from the global namespace, it's just like using the global command.

Hmmm.

I suppose you should just make another function - like rglobal (from 
request global). I sometimes used global when I shared data across 
namespaces - mostly in code loaded at startup.

I suppose it could mislead some people who know exactly how does global 
work.

I suppose it should be a separate command and it should be mentioned in 
the docs - so that new users do not get confused about global.

>     The commands I'm using aren't written in the ::request namespace.
> We don't want to have to reload all of Rivet's commands everytime a
> request comes in, so we create the procs in the global namespace.  But,
> occassionally, I want to load global variables, and they actually do get
> loaded in stack #0.  Then, when ::request is destroyed, they still hang
> around, and can cause really spurious errors later on.

proc hglobal {args} {
     foreach v $args {
         uplevel [list upvar #0 ::request::$v $v]
     }
}

proc hvar {args} {
     set n ::request::[uplevel {namespace current}]
     namespace eval $n {}
     foreach v $args {
         uplevel [list upvar #0 ${n}::$v $v]
     }
}

The second one would create connection&namespace specific variables...
--
WK


---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org


Re: Global

Posted by Damon Courtney <da...@your.unreality.com>.
> Why not just use 'variable' instead of global?
> 
> -- SNIP --
> If the variable command is executed inside a Tcl procedure, it creates 
> local variables linked to the corresponding namespace variables. In this 
> way the variable command resembles the global command, although the 
> global command only links to variables in the global namespace.
> -- SNIP --

    Oh, I know the variable command well.  I do most of my programming
in namespaces to avoid collusion, but that doesn't help me here.  The
commands I'm creating are in the global namespace.  If I use the variable
command from the global namespace, it's just like using the global command.

    The commands I'm using aren't written in the ::request namespace.
We don't want to have to reload all of Rivet's commands everytime a
request comes in, so we create the procs in the global namespace.  But,
occassionally, I want to load global variables, and they actually do get
loaded in stack #0.  Then, when ::request is destroyed, they still hang
around, and can cause really spurious errors later on.

D


---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org


Re: Global

Posted by Wojciech Kocjan <wo...@kocjan.org>.
Why not just use 'variable' instead of global?

-- SNIP --
If the variable command is executed inside a Tcl procedure, it creates 
local variables linked to the corresponding namespace variables. In this 
way the variable command resembles the global command, although the 
global command only links to variables in the global namespace.
-- SNIP --

A small example:

namespace eval x {
     proc y {} {
         variable z
         incr z
         return $z
     }
     set z 0
}

% x::y
1
% x::y
2
% x::y
3

When I write a script/engine, I do the following:

namespace eval somename {}

proc somename::someproc {} {
     variable d
     set d(something) [something]
}

It's much easier and nicer to use namespace local variables :>

--
WK


---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-dev-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-dev-help@tcl.apache.org