[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Converting setfenv getfenv to Lua 5.2
- From: Georgios Petsagourakis <petsagouris+lual@...>
- Date: Sat, 30 Nov 2013 17:33:26 +0000 (UTC)
Andrew Starks <andrew.starks <at> trms.com> writes:
>
> Without rewriting the code that you posted:
>
> The part that you showed that isn't directly included in 5.2 is the
> ability to extract a function's environment after it's been passed in.
> To accomplish the same outcome in 5.2, some good old refactoring needs
> to take place. Presumably (or I could look it up and verify it) this
> was because doing so breaks some basic rules that should be more
> difficult to break (debug library) or done explicitly, by changing the
> way that `func` is implemented.
>
> Some refactoring strategies:
>
> Rewrite the function so that you can pass in an environment. I haven't
> done much of this but func's arguments would start with _ENV
>
> local func(_ENV, ...)
> ---code that does stuff, using the provided _ENV
> end
In this I assume you mean something like this:
local function something(env, ...)
local old_env = _ENV
_ENV = env
-- do code here, `env` is your environment
_ENV = old_env
end
>
> ---if you wanted to keep the current env as a shadow:
>
> local func(env, ...)
> _ENV = setmetatable(env, {__index = _ENV}) --or the other way around
> ---code that does stuff
> end
I am not clear here, shouldn't the initial _ENV be restored at some point ?
> ----------
>
> I'm not sure if my answer is too basic or not. Nobody answered right
> away, so I thought I'd start here. Let me know if I'm off...
>
You are not off at all, it is hard to restructure such small modules
without thinking that you are actually producing a fork of some sort.
The changes are not trivial in any way. They might even break backwards
compatibility which in itself is not a good thing.
> _ENV is the first upvalue of every scope and points to the previ to
> the previous scope's _ENV, which at the very top-most level is _G. You
> probably know this, but it bares stating because that's all it is.
>
> Therefore, to stash a current environment `local env = _ENV` and to
> default to an old _ENV `setmetatable(_ENV, {__index = env})` and to do
> anything fancier, assign `__index` to a function that does stuff, as
> your function did.
>
Nice explanation, thanks for putting this into words.