setfenv

getfenv

x = 3 function print_x () print (x) end print_x() setfenv (print_x, { print = print , x = 4 }) print_x() print ( getfenv (print_x).x)

In Lua 5.2-work3, this environment table is gone. Instead, globals are resolved in a special upvalue called _ENV , and every piece of code loaded (even if it doesn't access any globals) is done so in the context of an upvalue called _ENV , which is initialised to the value of the globals table ( LUA_RIDX_GLOBALS in the registry, see later) at the time of the loading. This means that code like the following works:

do local outer = _ENV local _ENV = {} function outer.set_x (value) x = value end function outer.get_x () return x end function outer.set_inner_env (e) _ENV = e end end set_x( 5 ) print (x) print (get_x()) set_inner_env{x = 10 } print (get_x())

Note that _ENV behaves like a shared upvalue, which is different to how setfenv / getfenv used to work, and different to _G . Specifically, all functions within a chunk (a piece of loaded code) share the same environment unless they specifically redeclare a local called _ENV, so setting the environment of one of them (e.g. with debug.setupvalue ) will affect all of them. The global variable _G is still present, and the initial value of _G is the same as the initial value of _ENV , but changing one has no effect on the other, though as _G is a global, it really means _ENV._G in 5.2-work3, so changing _ENV to something without a _G field will make _G evaluate to nil . Also note that as an upvalue, _ENV can take any type of value, not just a table. Hence the following can be done:

local print = print do local _ENV = "some string" print (gsub) end do local _ENV = nil print ( io ) end