[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Globals (more ruminations)
- From: HyperHacker <hyperhacker@...>
- Date: Wed, 21 Jul 2010 14:45:55 -0600
On Wed, Jul 21, 2010 at 11:43, Stuart P. Bentley <stuart@testtrack4.com> wrote:
> On Fri, 16 Jul 2010 12:38:32 -0400, Roberto Ierusalimschy
> <roberto@inf.puc-rio.br> wrote:
>
>> Repeating again: the point is not to disallow global access, but to
>> prevent unintended creation of globals. Changing the environment
>> prevents the unintended creation of globals, but at a high cost (no
>> more access to globals including the standard libraries):
>>
>> do
>> local _ENV = nil
>> a = 12345 --would result in "error: no environment"; fine
>> local a = 12 -- fine, 'a' now is local
>> print(a) -- oops; error...
>> end
>>
>> -- Roberto
>>
>>
>
> What about this?
>
> do
> local G = _ENV -- save the environment in a local G
>
> local _ENV = nil -- remove the reference to the global table as environment
>
> G.a = 12345 -- "global variables" would just be explicit indexes -
> -- the downside would be that any use of the global "a" would
> need
> -- a couple characters before every use, but if the developer
> chose to
> -- remove the environment, it's safe to say they're OK with
> that,
> -- and if they have to use globals a lot again in one section
> -- of the code they can just enclose it within a "do local _ENV
> = G ... end"
>
> local a = 12 -- all plain references to "a" unambiguously point to this
> local
>
> -- Now, two ways to access print and all other globals including the
> standard libraries:
> G.print(a) -- explicitly index it out of the global table
>
> -- or --
>
> local print = G.print -- or local print = print if you do it before
> -- removing the environment
> print(a)
>
> end
>
> Module authors have been using these two approaches (explicit indexing and
> localization) for years without complaint.
>
>
I think a lot of the suggestions made so far are basically syntactic
sugar for this. If you're using a lot of functions from the global
namespace it'd be somewhat annoying to have to do "local print, io,
string, table = G.print, G.io, G.string, G.table" etc all the time.
Perhaps a solution here is a "_module" table, which works similar to
_G, containing all modules that have been loaded to the global
namespace. i.e. at startup it would contain {string, os, io} etc as
well as perhaps some of the built-in globals like print, package, and
pcall (or perhaps these should be in modules of some sort as well).
The problems I can see with this are how to keep track of the module
tables - with the current system a module isn't required to return
itself to a require() call, and can just toss as many tables into the
global namespace as it likes; we'd have to catch those tables and make
references to them in _module. There's also the possible issue of
opening up another "backdoor" to io, os etc to sandboxed scripts
written for 5.1, but it should only take a few lines to fix that (even
just setting _module to nil).
For the former problem, maybe require() can just add any globals that
are present after loading the module that weren't before. This might
catch a few globals-that-should-be-locals, but I guess that's just
another reason to encourage proper use of locals. :-)
--
Sent from my toaster.
- References:
- Re: Globals (more ruminations), Alexander Gladysh
- Re: Globals (more ruminations), Roberto Ierusalimschy
- Re: Globals (more ruminations), Juri Munkki
- Re: Globals (more ruminations), Roberto Ierusalimschy
- Re: Globals (more ruminations), Patrick Donnelly
- Re: Globals (more ruminations), Roberto Ierusalimschy
- Re: Globals (more ruminations), Edgar Toernig
- Re: Globals (more ruminations), David Manura
- Re: Globals (more ruminations), David Manura
- Re: Globals (more ruminations), Stuart P. Bentley
- Re: Globals (more ruminations), Roberto Ierusalimschy
- Re: Globals (more ruminations), Stuart P. Bentley