_ENV vs _G

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

Re: _ENV vs _G

Dirk Laurie-2
2014-08-13 9:38 GMT+02:00 Tim Hill <[hidden email]>:

>
> On Aug 13, 2014, at 12:17 AM, Dirk Laurie <[hidden email]> wrote:
>
>>>>>
>>>>> 4. If you compile a function using `load` or `loadstring`, its _ENV is one
>>>>> of:
>>>>> a. An _ENV parameter.
>>>>> b. The _ENV specified in the `load`.
>>>>> c. An _ENV upvalue.
>>>>>
>>>>
>>>> It's only the one specified in the registry if that still happens to be
>>>> the current upvalue called _ENV. And even the one in the registry
>>>> may not be the one you started with. You can assign something
>>>> to debug.getregistry[2]; not recommended, though.
>>>
>>>
>>> That’s not my reading of the docs/source, though they are rather
>>> unclear.
>>
>> Have you read my code in env.lua, verified that it gives the specified
>> results, and checked my logic in claiming why it gives those results?
>>
>> If not, there is not much point in my trying to argue with you.
>>
>
> Indeed I did, though I was discussing and not arguing.
> Perhaps we are talking about different things. My reading of your
> post was that a compiled chunk (which is, by definition, a function)
> could have any of (a), (b) or (c) as it’s _ENV. My point was that this
> isn’t true, it can only be (b) or the distinguished environment.

If by "compiled chunk" you mean "the result of `load` or `loadfile`
with no _ENV argument" I almost, but not quite, agree. [1]

If by "distinguished environment" you mean "the original global
environment of the Lua state created by the host program",
I almost, but not quite, agree. [2]

> If, however, you mean that lexically NESTED functions WITHIN
> a compiled chunk may have (a), (b) or (c) then yes of course
> that is true as per the Lua documentation.

That is what my code demonstrates, so yes, I mean it.

[1] Binary chunks can have _ENV parameters, so (a) is possible.
[2] The correct description is "the global environment stored
in the registry at the time the chunk is loaded". Demo:
$ lua
Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
> f = load"return _ENV, id"
> debug.getregistry()[2] = {id="mytable",f=f,load=load,print=print,tostring=tostring}
> g = load"return _ENV, id"
> =f()
table: 0x1fe05f0    nil
> =g()
table: 0x2003f10    mytable

But you are right that (c) is impossible for a loaded chunk, since
merely `_ENV = ` instead of `debug.getregistry()[2] =` does not have
the above effect.

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Tim Hill

On Aug 13, 2014, at 4:55 AM, Dirk Laurie <[hidden email]> wrote:

If by "distinguished environment" you mean "the original global
environment of the Lua state created by the host program",
I almost, but not quite, agree. [2]

I was using it as defined in section 2.2 of the ref manual, which defines it to mean that very thing; whatever environment is currently at the well-known registry index; though the manual is slightly ambiguous on this point (it might mean that the distinguished environment is the ORIGINAL one in the registry, or the CURRENT one)..

[1] Binary chunks can have _ENV parameters, so (a) is possible.

Interesting, how do you do that?

—Tim

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Dirk Laurie-2
2014-08-13 20:00 GMT+02:00 Tim Hill <[hidden email]>:
> On Aug 13, 2014, at 4:55 AM, Dirk Laurie <[hidden email]> wrote:
> [1] Binary chunks can have _ENV parameters, so (a) is possible.
>
>
> Interesting, how do you do that?

$ lua
Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
> f=function(_ENV) return _ENV,id end
> cf=string.dump(f)
> io.open("f.luac","wb"):write(cf):close()
>
$ lua
Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
> f=loadfile"f.luac"
> print(_ENV)
table: 0x1f205f0
> return f{id="my_env"}
table: 0x1f440d0    my_env

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Tim Hill

On Aug 13, 2014, at 1:34 PM, Dirk Laurie <[hidden email]> wrote:

> 2014-08-13 20:00 GMT+02:00 Tim Hill <[hidden email]>:
>> On Aug 13, 2014, at 4:55 AM, Dirk Laurie <[hidden email]> wrote:
>> [1] Binary chunks can have _ENV parameters, so (a) is possible.
>>
>>
>> Interesting, how do you do that?
>
> $ lua
> Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
>> f=function(_ENV) return _ENV,id end
>> cf=string.dump(f)
>> io.open("f.luac","wb"):write(cf):close()
>>
> $ lua
> Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
>> f=loadfile"f.luac"
>> print(_ENV)
> table: 0x1f205f0
>> return f{id="my_env"}
> table: 0x1f440d0    my_env
>

Ah, interesting border-case. In fact, even if you DO specify an environment to loadfile() in this case it will be inaccessible to the function.

I’ve not really given it much thought, but a function that declares _ENV as one of its arguments in fact has NO access to the global environment at all so far as I can see (except indirectly via upvalues or other arguments, both of which the caller can control). Is this, then, a Lua idiom for writing (partially) pure functions? With the obvious caveat that such a function is free to call impure functions.

—Tim


Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Coda Highland
On Wed, Aug 13, 2014 at 2:50 PM, Tim Hill <[hidden email]> wrote:

>
> On Aug 13, 2014, at 1:34 PM, Dirk Laurie <[hidden email]> wrote:
>
>> 2014-08-13 20:00 GMT+02:00 Tim Hill <[hidden email]>:
>>> On Aug 13, 2014, at 4:55 AM, Dirk Laurie <[hidden email]> wrote:
>>> [1] Binary chunks can have _ENV parameters, so (a) is possible.
>>>
>>>
>>> Interesting, how do you do that?
>>
>> $ lua
>> Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
>>> f=function(_ENV) return _ENV,id end
>>> cf=string.dump(f)
>>> io.open("f.luac","wb"):write(cf):close()
>>>
>> $ lua
>> Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
>>> f=loadfile"f.luac"
>>> print(_ENV)
>> table: 0x1f205f0
>>> return f{id="my_env"}
>> table: 0x1f440d0    my_env
>>
>
> Ah, interesting border-case. In fact, even if you DO specify an environment to loadfile() in this case it will be inaccessible to the function.
>
> I’ve not really given it much thought, but a function that declares _ENV as one of its arguments in fact has NO access to the global environment at all so far as I can see (except indirectly via upvalues or other arguments, both of which the caller can control). Is this, then, a Lua idiom for writing (partially) pure functions? With the obvious caveat that such a function is free to call impure functions.
>
> —Tim

It feels to me more like a "with" block than any sort of functional idiom.

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: _ENV vs _G

Tim Hill

On Aug 13, 2014, at 3:00 PM, Coda Highland <[hidden email]> wrote:

>>
>> Ah, interesting border-case. In fact, even if you DO specify an environment to loadfile() in this case it will be inaccessible to the function.
>>
>> I’ve not really given it much thought, but a function that declares _ENV as one of its arguments in fact has NO access to the global environment at all so far as I can see (except indirectly via upvalues or other arguments, both of which the caller can control). Is this, then, a Lua idiom for writing (partially) pure functions? With the obvious caveat that such a function is free to call impure functions.
>>
>> —Tim
>
> It feels to me more like a "with" block than any sort of functional idiom.
>
> /s/ Adam
>

Yes, possibly. In either case it’s just a minor observation.

—Tim


123