[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 01:35:44 -0400
It was thus said that the Great Dirk Laurie once stated:
> 2015-03-28 6:05 GMT+02:00 Sean Conner <sean@conman.org>:
>
> > 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.
>
> First, let's explain _ENV.
[ snip ]
> Now when you change _ENV, in whatever way, the original global
> environment is invisible unless you have in some way kept it. E.g.
Yes, I know all this. You still haven't explained upvalues though.
Okay, now that I've thought about this, I think I know how upvalues are
actually implemented. You define a local variable, some space is set aside
to store values:
+------+
location X: | _ENV |
+------+
+------+
location Y: | BOB |
+------+
Now, let's create two functions that reference this variable:
function foo(x)
_ENV.print(BOB + x)
end
function bar(x)
return _ENV.tostring(BOB - x)
end
Each function has an upvalue for _ENV and BOB. These upvalues are
pointers [1] to the actual variables:
foo
upvalue 1 location X -- illustrative purposes
upvalue 2 location Y -- only
bar
upvalue 1 location Y
upvalue 2 location X
When you call debug.setupvalue(), say:
debug.setupvalue(foo,2,99)
it stores the 99 in location Y, that being the location of the variable
storing the upvalue in slot 2 of foo. So of course, when you change the
upvalue for _ENV, you are not changing the location of the upvalue but the
location that upvalue is pointing to. So doing
debug.setupvalue(bar,2,{ })
updates location X with an empty table, which in this case, is not only the
environment for foo, but probably the global environment. The upvalue 2 for
bar hasn't changed, as it's still pointing to location X, but location X has
changed!
I think what caught me up is that I haven't really played with Lua 5.2 (or
Lua 5.3 until a few days ago) and I was still kind of expecting the Lua 5.1
behavior with setfenv(), which is a "local" change of a function's
environment, and not the global change that happens now (because upvalues
are pointers).
-spc (So now that I've explained it to me like I was five, I think I'm
done here)
[1] Sorry for the Cism here, but that's how I have to think about this.