lua-users home
lua-l archive

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

Andrew Starks <andrew.starks <at>> 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

> ---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.