lua-users home
lua-l archive

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


I suppose I should’ve said _ENV==_G
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
>> 
> 
>