[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: changing global environments
- From: Eike Decker <eike@...>
- Date: Sun, 25 Mar 2007 00:44:12 +0100
You could simulate such a behavior by using metatables in the environment
tables. Like this:
environment = {}
setmetatable(environment,
{
__index = function (self,key)
local value = _G[key]
if type(value) == "function" then
return function (...)
local prevenv = getfenv(value)
pcall(setfenv,value,environment)
-- C Function environments cannot be overridden
-- and will throw error, thus just pcall it
local arg = {value(...)}
pcall(setfenv,value,prevenv)
return unpack(arg)
end
end
return value
end
}
)
function boo ()
print("environment value: a =",a)
end
function foo ()
boo()
end
function sandbox ()
a = 10 -- set a to 10, but this will only affect
-- the environment table, not _G!
foo()
end
setfenv(sandbox,environment)
foo() -- prints out a = nil
sandbox() -- prints out a = 10 - boo() inherited environment
foo() -- prints out a = nil again - just correct
-- end
The problem here is, that it is not performant (at least not this code) and its
also not very elegant. Setting the environment tables each call... that's not
pretty. But at least it works - as long as no C Function is hit that calls a
lua function again. You have to override the C Functions then with lua
functions that handle these special cases.
But maybe there's an more elegant solution for that problem.
Eike
> Hi,
>
> Is there any way to set the environment of a function such that all
> functions it calls will also inherit this environment? In the
> example below, I change the environment of fmain, which in turn calls
> fsub, but the environment of fsub is unchanged.
>
> I also tried changing the environment in fmain using setfenv(1, e)
> but it still doesn't affect fsub. Setting the global environment via
> setfenv(0, e) affects everything in the program. Would changing the
> environment via C (LUA_GLOBALSINDEX perhaps?) achieve what I want, or
> is that the equivalent of setfenv(0)? Basically, is it possible for
> a function to have the environment dynamically bound, or is it fixed
> at creation/setfenv time?
>
> fsub = function()
> print("fsub", getfenv(0), getfenv(1))
> b = 1
> end
>
> fmain = function()
> print("fmain", getfenv(0), getfenv(1))
> a = 1
> fsub()
> end
>
> e = { __index = getfenv(0) }
> setmetatable(e, e)
>
> setfenv(fmain, e)
>
> fmain()
>
> print(a, b)
> print(e.a, e.b)
>
> outputs:
> fmain table: 0x1452a450 table: 0x1452f010
> fsub table: 0x1452a450 table: 0x1452a450
> nil 1
> 1 1
>
>
>
>
>
>