[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Bizarre behavior with debug.setupvalue() in Lua 5.3
- From: Sean Conner <sean@...>
- Date: Sat, 28 Mar 2015 00:05:24 -0400
It was thus said that the Great Soni L. once stated:
>
> On 27/03/15 11:06 PM, Sean Conner wrote:
> >It was thus said that the Great Tim Hill once stated:
> >>>On Mar 27, 2015, at 2:28 PM, Sean Conner <sean@conman.org> wrote:
> >>>
> >>> I would expect setting the first upvalue of meta.print() to meta would
> >>>make meta the default global environment for meta.print() and not replace
> >>>the current global environment.
> >>>
> >>Actually, the compiler makes no guarantees about which upvalue (if any)
> >>for a function contains the _ENV environment EXCEPT in the case of the
> >>implicit anonymous function that wraps a compiled chunk. The load() API
> >>family always sets the first upvalue to the environment because it assumes
> >>that the chunk being loaded was a compiled chunk (rather than an explicit
> >>function within a chunk that was accessed with string.dump().
> > But that isn't the issue. Even if I got the wrong index, I did not
> > expect
> >the global environment to change---only the environment for meta.print().
> >
> > -spc
>
> You're changing the _value_ of the upvalue and expecting the _upvalue_
> to change...
Then perhaps I have the wrong mental image of how upvalues work in Lua,
because it's doing things I don't expect.
Okay, explain to me like I'm five how this works.
I have the following code:
local a = 3
function foo(x)
local y = 4 * x + a
print(y)
return y
end
foo(3)
I run it. I get 15. Okay, let me change the upvalue "a" [1]
debug.setupvalue(foo,1,4)
foo(3)
print(a)
And I get 16 (expected) and 4 (also expected). Now, let's see about
changing the _ENV on that sucker:
debug.setupvalue(foo,2,{ print = print })
foo(3)
lua-53: z.lua:16: attempt to call a nil value (global 'foo')
stack traceback:
z.lua:16: in main chunk
[C]: in ?
WTF? That is NOT what I expected. Let me think on this ...
Okay, it's clear tha upvalues aren't copies of values, but references to
values. That's why
debug.setupvalue(foo,1,4)
also changed "a". So when I do
debug.setupvalue(foo,2,{ print = print })
I'm changing the default _ENV as well.
I won't say that sucks, but it does come across as unintuitive behavior.
But I will say that having to jump through hoops to change a function's
environment *after it's compiled* sucks [2].
I also think I've come across a bug in Lua 5.3, but I'll leave that for
another message.
-spc (Or it could be undefined behavior, I'm not sure ... )
[1] It's the first upvalue; _ENV is the second upvalue. I know this
because of the following code not included in the above:
info = debug.getinfo(foo,"u")
for i = 1 , info.nups do
name,value = debug.getupvalue(foo,i)
print(i,name,value)
end
It's consistent between runs. There you go.
[2] So how do I get setfenv() in Lua 5.3 again?