lua-users home
lua-l archive

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


Just to clarify, (not that any of you care) I realized that although I did forget that _ENV._G is the same as _G, it actually wasn’t the forgotten property that lead to my initial confusion about the relationship between _ENV and _G. What I said in the initial email is that _ENV and _G couldn’t be the same because when you set _G=nil, _ENV doesn’t become nil. I was just being stupid because my brain was thinking when two variables reference the same table, changing one changes the other to the same value (which is obviously false), tsk tsk brain. Also, so far it seems like _G is the equivalent Lua 5.2’s appendix.
On Aug 11, 2014, at 2:13 PM, Mason Mackaman <masondeanm@aol.com> wrote:

> 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
>> 
> 
>