lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Okay, I’ve figured out the relationship between _G and _ENV, _ENV=_G. The reason things were confusing me before is I had forgotten that _G is really _ENV._G, so that clears that up. But now the other part of my question is even bigger, What the hell is the point of _G?
On Aug 11, 2014, at 1:48 PM, Coda Highland <chighland@gmail.com> wrote:

> On Mon, Aug 11, 2014 at 11:08 AM, Steven Degutis <sbdegutis@gmail.com> wrote:
>> This is the other part that confused me:
>> 
>>   _ENV is the "global scope"
>> 
>> What does that mean? In the PiL^3 book, it says something similar, but
>> instead of _ENV = _G, it says _ENV = <global environment> which made
>> me think it was doing a special per-entry copy into a new table or
>> something.
>> 
>> So I guess it was how _ENV is populated that I was actually confused
>> about this whole time, and still am.
> 
> _ENV, unlike _G, does have one additional piece of magic: The language
> uses it when it can't find any other definition of a variable.
> 
> So suppose you have the following code:
> 
> local a
> a = 1
> b = 2
> 
> When this code starts executing, _ENV will be prepopulated by the
> language's standard library -- functions like type and print.
> 
> When it's done, it'll contain that, plus b, which will have the value
> of 2. The first assignment, "a = 1", will first look for a local named
> "a", and it finds one, so it uses it. But the second one, "b = 2",
> will look for a local named "b", fail to find it, and then look for
> one in _ENV. It won't find it there either, so it'll create a new key
> in the _ENV table named "b", and assign the value of 2 to it.
> 
> If this code is in a file or string that was loaded by something else
> (for example, if you require'd a file or loadstring'ed a chunk of
> code) then its _ENV will also contain anything that was put into _ENV
> before it was created.
> 
> But _ENV isn't always the same table -- you CAN assign a new table to
> it, and every chunk has its own _ENV. By default, the chunk's _ENV
> defaults to the _ENV of its creator (take note: the creator, not the
> caller).
> 
> So here's some brief demonstration (though I haven't run this for testing):
> 
> 
> 
> -- Keep track of the original ENV
> local oldenv = _ENV
> 
> -- We have to hold on to this, because loadstring is in _ENV
> local oldloadstring = loadstring
> 
> -- Set up a base case for demonstration
> x = 1
> print(x) -- outputs 1
> 
> -- Replace _ENV, create a new chunk
> _ENV = {}
> local mychunk = oldloadstring("x = 3")
> -- mychunk's _ENV is a reference to the table we just created
> 
> -- Demonstrate the behavior
> print(x) -- outputs nil
> mychunk()
> print(x) -- outputs 3
> 
> -- Put our original _ENV back
> _ENV = oldenv
> print(x) -- outputs 1
> 
> -- Observe that the new chunk has a different _ENV
> mychunk()
> print(x) -- still outputs 1
> 
> 
> 
> I hope I've been able to demystify things a bit. It took me a while to
> grok it myself; Lua 5.1's setfenv() seemed more intuitive to me until
> I really poked at the mechanics of _ENV, and now I see that _ENV has
> its advantages.
> 
> /s/ Adam
>