lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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.