lua-users home
lua-l archive

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

Mark Hamburg wrote:
> So, I can sympathize with the decision to deprecate setfenv
> and getfenv (though I've got some trepidation about shifting
> to the debug module). I view loadin as a decided improvement.
> But I'm not convinced yet that in-do-end really makes things
> enough better to be worth the syntax.

Well said.

My question: why are globals glued to closures anyway? [1]

It only makes sense when you want to changes globals.  If
there's no way to change them, there's no need to attach them
to each and every function).

So when do you want to change globals?  Mark has already
given some examples.  I would make it two categories:

  1) Sandboxing.  You want to run code in a special environment,
  either limited or customized.  Maybe even multiple times with
  different environments.

  2) Isolation.  You want to protect code from alien environments.
  The environment that was present when a function was created
  is available when the function is actually called.

Sandboxing: For me it seems, the current method of glueing globals
to functions makes live not really easy for sandboxing.  You can
change the environment of the entry function but every other
function called from within this function still has its original
environment and won't respect the sandbox environment.  Trying to
write functions that respect a changed environment is non-trivial.

Isolation: Lua has everything, even without function environments.
You just have to use locals.  You have to write a tiny little bit
more but on the other side it's faster than using globals.  You
have 100% control over what is used when a function runs (without
any tricks), you just have to be explicit about it.

The problem is that sandboxing and isolation are the two sides
of a coin: one wants to replace everything, the other wants to
protect everything.  IMHO, with the introduction of function
environments the balance swung to isolation and with the planned
introduction of the "in-do-end" syntax even more.

For a complex language like Java or C++, together with their
inherent control-mentality, that may be OK.  IMHO, for an dynamic
script language like Lua it's to complicated and unintuitive.
Possibly every function call switches the globals. Which ones
were active when the closure was created. Everything else vanishes
when using "in". ...

So, what was so wrong with Lua4's method of manipulating globals?
[For the "newcomers" ;-): One global table of globals, one function
to get/set it: old = globals([new]).]  IMHO nothing really funda-
mental.  The biggest, IMHO, failing to restore globals in case of
errors.  Functions expecting things to be there (including hooks).
[FYI, at those time there were no full lexically scoped locals.]
And then there was the introduction of threads which may require

Could this possibly resolved with a dynamic "in-do-end"?  That is,
"in env do <code> end" installs env as the new table of globals for
<code> and everything <code> calls.  When end is reached (or an
error is raised) the previous table is restored.  These in-do-end
should nest (I admit, it's not easy to get nesting fast).
No function environment any more, only a global environment.  If
functions want to protect against sandboxing, they have to deal
with that by themselves.

I have no idea whether all details of a dynamic in-do-end can be
defined reasonably (abort search, post write, direct access to
upper levels, thread creation, a=a+1, etc).  But I would prefer
this direction.  Just my opinion - I know there are people who
disagree.  And there are even people who use Boost ;-)

Another 2ct,

[1] Used terminology:

(table of) globals: a table which is used to look up
    non-local variables.

closure: the object you get when executing a function
    statement/expression.  Holds the code of the function
    plus references to currently active outer locals and
    to a globals table (the function environment).

(function) environment: the globals attached (or to be
    attached) to a closure.

function call: used as a synonym for closure call.