lua-users home
lua-l archive

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

Roberto Ierusalimschy wrote:
> I will try to answer the sereval requests for our rationale for the
> removal of setfenv/getfenv.
Thank you.

When you're done, could you pretty please explain why in-do made it in
to 5.2, but continue didn't and neither did an error handling mechanism
(try/catch?) less ugly than pcall? :)

> The main motivation was that, in our view, setfenv/getfenv was too
> dynamic.  Basically, if function A can call function B, it can also
> change the environment of B. If function A calls B, B can change the
> environment of A. In other words, almost anything can change the
> environment of anything.
> We tried to restrict such uses. Basically, if you create a new function,
> you can set its environment. Otherwise, the function itself should be
> responsible for its own environment (using lexical environments).
> Most uses easily fit this setting. Others may need extra work. For
> instance, more than one user talked about loading a piece of code once
> and running it whith different environments. I may be wrong, but
> I think the following code does it (suggested by lhf):
>   code = "string with the code to be loaded"
>   f = loadstring("in ... do " .. code .. " end")
My objection is that this doesn't replace the lost functionality.

For starters, since it requires a string or bytecode image, you can't
use it with closures - even if you get the bytecode by dumping an
existing closure it'll lose its upvalues when you do so. You're invoking
the compiler every time, which is likely to be a performance hit if this
is done at all often (and outright impossible in some environments). On
top of that, it's *ugly* and stands out as the sort of messy hack that
Lua is noteworthy for rarely needing.

It has been pointed out elsewhere in the thread that you can always
write a function to take an environment as an argument and use in-do to
voluntarily subject itself to that; and furthermore that if you don't
need to swap around environments, you can use loadin() (or something
nicer wrapped around it). However, sometimes you just need to run a
function that's *not* so obliging in a context other than the one it was
loaded in.

To that end, what's the objection to providing a means to create a copy
of a closure with a different environment? It avoids the problem* of
functions being able to arbitrarily mess with their callers'
environments and of changing the behaviour of other parts of the program
by changing function environments in-place, while still allowing the
execution of a closure in an environment other than the one in which it
was created.

* I would argue that this is no more a problem than metatables are, but
clearly you disagree.