_ENV vs _G

classic Classic list List threaded Threaded
46 messages Options
123
Reply | Threaded
Open this post in threaded view
|

_ENV vs _G

Mason Mackaman
So I was reading the reference manual to try to understand what role _G plays in a Lua program and I’m not having much luck. Adding an element to _G adds it to _ENV, but setting _G=nil doesn’t delete _ENV, so I know they aren’t referencing the same thing. If you do take the time to help this noob out, could you please include in your answer the importance having both _ENV and _G, thanks.
Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Steven Degutis
I've also been pretty confused on what _G does specifically.

The docs are a little unclear about its role, and the book Programming
in Lua (third edition) isn't much more clear. The docs for _G says
"Lua itself does not use this variable; changing its value does not
affect any environment, nor vice-versa." From this, it's not clear to
me what operations do and do not affect it.

It also says in section 2.2, "Lua keeps a distinguished environment
called the global environment. This value is kept at a special index
in the C registry (see §4.5). In Lua, the variable _G is initialized
with this same value." This makes it clear to me that _G just
references a table somewhere in LUA_REGISTRYINDEX, at least I think
so.

But then this next part of the manual confuses me: "When Lua compiles
a chunk, it initializes the value of its _ENV upvalue with the global
environment (see load). Therefore, by default, global variables in Lua
code refer to entries in the global environment." -- Does this mean we
can assume that the literal code "_ENV = _G" is being executed, and
thus _ENV is by default literally just another reference to _G?

Assuming that's true, this part makes sense to me: "If you change the
global environment in the registry (through C code or the debug
library), all chunks loaded after the change will get the new
environment. Previously loaded chunks are not affected, however, as
each has its own reference to the environment in its _ENV variable."
because _ENV is an upvalue referencing the table that was previously
also referenced by _G (i.e. a special spot in LUA_REGISTRYINDEX).

And if it's true, then I /think/ I understand the final sentence of
section 2.2: "Moreover, the variable _G (which is stored in the
original global environment) is never updated by Lua." -- so if the
variable _G is just a reference to the same table that exists in
LUA_REGISTRYINDEX, then this implies that all operations /on/ this
table will affect "the global environment", whereas changing what this
variable itself points to will do nothing, since Lua does not actually
reference a global called "_G" in its code.

Is this the correct interpretation? If so, the manual could definitely
use some clarifications here, ideally relying on familiar terminology
that's not so ambiguous.

Disclaimer: I'm pretty sure I understand how _ENV works perfectly
fine, my email is only about _G, unlike the original email. The manual
and Programming in Lua (third edition) were very clear and elaborated
at great length about how _ENV works and how to use it.

On Mon, Aug 11, 2014 at 11:39 AM, Mason Mackaman <[hidden email]> wrote:
> So I was reading the reference manual to try to understand what role _G plays in a Lua program and I’m not having much luck. Adding an element to _G adds it to _ENV, but setting _G=nil doesn’t delete _ENV, so I know they aren’t referencing the same thing. If you do take the time to help this noob out, could you please include in your answer the importance having both _ENV and _G, thanks.

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Coda Highland
On Mon, Aug 11, 2014 at 10:31 AM, Steven Degutis <[hidden email]> wrote:
> I've also been pretty confused on what _G does specifically.

Instead of trying to respond to the contents of the e-mails, I'll give
a very short explanation.

When a chunk (usually a file, but also anything you've created with
something like loadstring) starts, _G is a reference to _ENV.

(_ENV is the "global scope", and any variable references that can't be
found as local definitions or upvalues are looked up in the _ENV
table. You can explicitly look inside _ENV if you want to grab a
global that was shadowed by a local or upvalue.)

Beyond that, there's absolutely nothing magical about _G. Its purpose
is to be a reference to the original _ENV if you replace it. All of
the remaining commentary is just a description of how non-magical _G
is.

That's literally all there is to it.

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Steven Degutis
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.

On Mon, Aug 11, 2014 at 12:37 PM, Coda Highland <[hidden email]> wrote:

> On Mon, Aug 11, 2014 at 10:31 AM, Steven Degutis <[hidden email]> wrote:
>> I've also been pretty confused on what _G does specifically.
>
> Instead of trying to respond to the contents of the e-mails, I'll give
> a very short explanation.
>
> When a chunk (usually a file, but also anything you've created with
> something like loadstring) starts, _G is a reference to _ENV.
>
> (_ENV is the "global scope", and any variable references that can't be
> found as local definitions or upvalues are looked up in the _ENV
> table. You can explicitly look inside _ENV if you want to grab a
> global that was shadowed by a local or upvalue.)
>
> Beyond that, there's absolutely nothing magical about _G. Its purpose
> is to be a reference to the original _ENV if you replace it. All of
> the remaining commentary is just a description of how non-magical _G
> is.
>
> That's literally all there is to it.
>
> /s/ Adam
>

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Roberto Ierusalimschy
In reply to this post by Steven Degutis
> [...]
>
> Is this the correct interpretation? If so, the manual could definitely
> use some clarifications here, ideally relying on familiar terminology
> that's not so ambiguous.

Your interpretation until this point was quite correct (and it seems
to have been derived from the manual). What is so ambiguous in that
terminology?


> This is the other part that confused me:
>
>    _ENV is the "global scope"

Where did you read this? In the manual?


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

No assignment in Lua creates a new table. Why this one would be different?

What it does is equivalent to "_ENV = _G", but it does not use _G
itself (remember that Lua never uses _G); instead, it uses the private
reference to the global table kept in the registry, so the notation
<global environment>.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Coda Highland
In reply to this post by Steven Degutis
On Mon, Aug 11, 2014 at 11:08 AM, Steven Degutis <[hidden email]> 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

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Coda Highland
In reply to this post by Roberto Ierusalimschy
On Mon, Aug 11, 2014 at 11:34 AM, Roberto Ierusalimschy
<[hidden email]> wrote:
>> This is the other part that confused me:
>>
>>    _ENV is the "global scope"
>
> Where did you read this? In the manual?

In my e-mail; I'd used that phrase in quotes to indicate that I wasn't
literally saying it was the global scope, but that it could be seen as
a similar concept.

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Mason Mackaman
In reply to this post by Coda Highland
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 <[hidden email]> wrote:

> On Mon, Aug 11, 2014 at 11:08 AM, Steven Degutis <[hidden email]> 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
>


Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Geoff Leyland
On 12/08/2014, at 7:13 am, Mason Mackaman <[hidden email]> 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?

I thought it was a leftover from 5.1 that just hadn’t been removed yet
Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Mason Mackaman
In reply to this post by Mason Mackaman
I suppose I should’ve said _ENV==_G
On Aug 11, 2014, at 2:13 PM, Mason Mackaman <[hidden email]> 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 <[hidden email]> wrote:
>
>> On Mon, Aug 11, 2014 at 11:08 AM, Steven Degutis <[hidden email]> 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
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Dirk Laurie-2
In reply to this post by Mason Mackaman
2014-08-11 21:13 GMT+02:00 Mason Mackaman <[hidden email]>:
> 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?

Good question, since if you have clobbered _ENV then _ENV._G is no
longer accessible either.

But the test

if tbl==tbl._G then
   print "I'll bet `tbl` is the original global environment"
end

is likely to be correct unless you have been clobbering _G.

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Tim Hill
In reply to this post by Roberto Ierusalimschy

On Aug 11, 2014, at 11:34 AM, Roberto Ierusalimschy <[hidden email]> wrote:

[...]

Is this the correct interpretation? If so, the manual could definitely
use some clarifications here, ideally relying on familiar terminology
that's not so ambiguous.

Your interpretation until this point was quite correct (and it seems
to have been derived from the manual). What is so ambiguous in that
terminology?

The 5.2 ref manual (section 2.2) states “When Lua compiles a chunk it initializes the value of its _ENV upvalue…”. When I was initially studying Lua this did confuse me until I realized that it really means “When Lua LOADS a chunk…” (which of course might also entail compiling it unless a pre-compiled chunk was supplied). When I first read this is seemed to suggest that the compiler was emitting some magic bytecode that, when later loaded, would wire-up _ENV to the global environment.

—Tim

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Tim Hill
In reply to this post by Mason Mackaman

On Aug 11, 2014, at 12:13 PM, Mason Mackaman <[hidden email]> 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?
>

Not quite. The whole _ENV and _G thing can appear a bit messy, and partly this is historical. Here’s the way it works (with some simplifications)...

Inside Lua is a special built-in table (a Lua table) known as the Registry. It is NOT normally accessible to Lua, but is accessible to C code via the Lua API. (There is actually one registry per main Lua state, but that’s not important for this discussion.) Stored at a well-known key (index) in this Registry is another Lua table which is the “distinguished environment” otherwise known as the table that holds Lua globals (as you know Lua globals are just values in a Lua table). When this global variable table is first created, the _G entry in the table is also set to reference the table (a self-reference). This only happens once (I’m not absolutely certain of this, but it seems to be implied by the docs).

When any Lua chunk is compiled and loaded, it starts off life as a Lua function (actually a closure) on the Lua stack ready to be called (all chunks are compiled as functions). This function will always have an upvalue named _ENV.. By default, the compiled function will have _ENV initialized to the “distinguished environment” that is stored in the Registry as explained above. However, you can, at chunk compile/load time, supply a *different* table to use as the value of _ENV for that chunk (see the various load() functions). The content of this custom table is entirely in your control, in particular Lua makes NO attempt to place an _G entry in it.

Also, when a function is compiled, Lua treats all global variable accesses as if they were prefixed with “_ENV.”, hence “foo” is converted to “_ENV.foo”. By default, this means that all global variable accesses are converted to table lookups in the table stored in the _ENV upvalue. And, as explained above, this table is either the distinguished environment or another table supplied by you when the chunk was compiled/loaded.

However, the _ENV name is not magical, apart from it’s being used to decorate global variable names by the compiler. Once the compiler has added the “_ENV.” prefix it treats the name normally. This means you can write code like this in Lua:

foo = 10
local _ENV = { foo=20 }
print(foo)

In both cases, “foo” is converted to “_ENV.foo”. However, in the first case, “_ENV.foo” refers to the table in the _ENV upvalue, while in the second case “_ENV.foo” refers to the foo value in the newly created local _ENV table (and hence will print 20).

How does this all relate to _G? The ONLY thing Lua does is set _G in the initial distinguished environment. That’s it. _G pre-dates the use of _ENV (which was new in Lua 5.2), and my assumption is that it was intended (among other things) to allow functions to run in explicitly specified global environments, for example:

function doit(X, a, b)
        X.print(a+b)
end
doit(_G,10,20)

This kind of thing is no longer necessary with 5.2 as a result of the new _ENV model (which is much more elegant as it avoids the need for all the manual “X” decorations).

What all this means is that whatever is in _ENV at any point in your code *IS* the current global environment by definition, while what is in _G is whatever your code has defined it to be, and may or may not be what you intend/need.

—Tim







Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Ashwin Hirschi

> This means you can write code like this in Lua:
>
> foo = 10
> local _ENV = { foo=20 }
> print(foo)

You can write it, but it won't run... [since there's no more print! ;-)]

Ashwin.

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Coda Highland
On Mon, Aug 11, 2014 at 1:35 PM, Ashwin Hirschi <[hidden email]> wrote:

>
>> This means you can write code like this in Lua:
>>
>> foo = 10
>> local _ENV = { foo=20 }
>> print(foo)
>
>
> You can write it, but it won't run... [since there's no more print! ;-)]
>
> Ashwin.
>

Oops, I forgot to store print in a local in my example. :P I
remembered loadstring!

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Tim Hill
In reply to this post by Ashwin Hirschi

On Aug 11, 2014, at 1:35 PM, Ashwin Hirschi <[hidden email]> wrote:

>
>> This means you can write code like this in Lua:
>>
>> foo = 10
>> local _ENV = { foo=20 }
>> print(foo)
>
> You can write it, but it won't run... [since there's no more print! ;-)]
>
> Ashwin.
>

Well indeed.

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Mason Mackaman
In reply to this post by Mason Mackaman
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 <[hidden email]> 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 <[hidden email]> wrote:
>
>> On Mon, Aug 11, 2014 at 11:08 AM, Steven Degutis <[hidden email]> 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
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Dirk Laurie-2
2014-08-12 8:51 GMT+02:00 Mason Mackaman <[hidden email]>:

> Also, so far it seems like _G is the equivalent Lua 5.2’s appendix.

Maybe, for the sake of conceptual integrity, it could be deprecated
in Lua 5.3.

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Tom N Harris
On Tuesday, August 12, 2014 09:16:59 AM Dirk Laurie wrote:
> 2014-08-12 8:51 GMT+02:00 Mason Mackaman <[hidden email]>:
> > Also, so far it seems like _G is the equivalent Lua 5.2’s appendix.
>
> Maybe, for the sake of conceptual integrity, it could be deprecated
> in Lua 5.3.

I think it still has a place.

    local _ENV = setmetatable({}, {__index=_ENV})

    function print(...)
      _G.print("my print:", ...)
    end

There are three general scopes that most sensible programs will concern
themselves with: local, file (or module or class), and global. The first has
the `local' keyword, the second has the _ENV upvalue, and the last has _G.

--
tom <[hidden email]>

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Axel Kittenberger
Which can simply be circumvented if it wouldn't be there:

local _G = _ENV
local _ENV = setmetatable({}, {__index=_ENV})

function print(...)
    _G.print("my print:", ...)
end

I agree with Dirk, _G ought to be deprecated.


On Tue, Aug 12, 2014 at 12:51 PM, Tom N Harris <[hidden email]> wrote:
On Tuesday, August 12, 2014 09:16:59 AM Dirk Laurie wrote:
> 2014-08-12 8:51 GMT+02:00 Mason Mackaman <[hidden email]>:
> > Also, so far it seems like _G is the equivalent Lua 5.2’s appendix.
>
> Maybe, for the sake of conceptual integrity, it could be deprecated
> in Lua 5.3.

I think it still has a place.

    local _ENV = setmetatable({}, {__index=_ENV})

    function print(...)
      _G.print("my print:", ...)
    end

There are three general scopes that most sensible programs will concern
themselves with: local, file (or module or class), and global. The first has
the `local' keyword, the second has the _ENV upvalue, and the last has _G.

--
tom <[hidden email]>


123