[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua 5.2 and in-do-end
- From: Richard Hundt <richardhundt@...>
- Date: Mon, 25 Jan 2010 17:47:27 +0100
Mark Hamburg wrote:
On Jan 25, 2010, at 4:02 AM, Richard Hundt wrote:
David Burgess wrote:
On 25/1/2010 12:28 PM, Mark Hamburg wrote:
function pushenv( newenv )
local oldenv = getfenv( 1 ) -- However one gains access to it...
POUNCE. Methinks that the indoend thing would aided by a currentenv() function...
here's a hackish version:
function currentenv()
local getlocal = debug.getlocal
local e = nil
local x = 0
while true do
x = x + 1
local n,v = getlocal(2, x)
if not n then break end
if n == "(environment)" then
e = v
end
end
return e
end
The need to scan for a specially named local demonstrates just how hard it is to implement and how potentially expensive it is to execute a function to get the current environment in the presence of the in-do-end construct.
Sure.
So we can take your idea just one step further and decorate the proxy
with a currentenv() closure, a closure for pushenv() to make sure
they're chained, and bootstrap it:
local function _pushenv(inner, outer)
local proxy = { }
setmetatable(proxy, {
__index = function(_, k)
local v = inner[k]
return v ~= nil and v or outer[k]
end;
__newindex = inner
})
rawset(proxy, "currentenv", function() return inner end)
rawset(proxy, "pushenv", function(env) return _pushenv(env, proxy) end)
return proxy
end
_G.pushenv = function(env) return _pushenv(env, _G) end
_G.currentenv = function() return _G end
local env = { answer = 42 }
in pushenv(env) do
print(answer) --> 42
in pushenv({ question = "The number of petunias" }) do
print(question, answer) --> The number of ... 42
end
print(question) --> nil
end
print(answer) --> nil
-Rich