lua-users home
lua-l archive

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


After that long discussion about setfenv/getfenv, we are convinced
that both functions should belong to the debug API. Both clearly break a
function's abstraction, tampering with the "original meaning" of the
function. They are clearly quite similar to getupvalue/setupvalue,
as both groups manipulate the external variables of a function.           

At the same time, we are convinced that there are situations where
those functions may be quite useful. To reconcile both views, we are
reviewing our position that the debug library should be used only for
debuging (as has already been suggested by some). The debug library
still should be used with great care and parsimony, but it is a valid
tool for metaprogramming (e.g., sandboxing) and other needs.

We also came up with a new concept for environments in Lua 5.2; its
main merit is simplicity. Lua functions do not have environments any
more. The construction "in env do ... end" is gone too. The new rules
are really simple:

1) Any chunk is compiled as if surronded by the following code:

    local _ENV = <some value>; function (...) <chunk> end

By default, <some value> is the global table, but a chunk loaded with
'loadin(e, chunk)' will have 'e' there.

2) Any global name <var> (that is, a variable name without a visible
declaration) is changed to _ENV.<var>. This change is syntactic, meaning
that _ENV refers to whatever _ENV is visible at that point in the
code. (Because of rule 1, however, _ENV will never be a global name.)

That is it.


A few observations:

* There are no more global variables, from a semantics point of
view. There are no more GETGLOBAL/SETGLOBAL opcodes. The _ENV thing
concerns only the compiler.

* 'in env do body end' becomes 'do local _ENV=env; body end'.

* setfenv becomes 'set the upvalue named _ENV' (which is clearly
a debug operation). If the function is the main function of a chunk,
it must have only one upvalue, named _ENV.

* A function may allow its environment to be changed with the following
code:

  do
    local _ENV = _ENV
    function setenv(x) _ENV = x end
    function foo (...) ... end
  end

Now, a call to 'setenv(t)' makes 't' the environment for 'foo'.

* Another alternative is to add _ENV as an argument to the function:

  function foo (_ENV, ...) ... end

Now 'foo's environment is passed to it at each call.

* Environments for C functions should go too. Actually, they were
introduced only to match environments in Lua functions. The old
technique of setting a table as a common upvalue for all functions
of a library (as done in Lua 5.0) is quite satisfying. (So, the
only "environments" left are for userdata, which probably should
get a more proper name.)

-- Roberto