lua-users home
lua-l archive

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


On Wed, Feb 24, 2010 at 7:53 PM, Nevin Flanagan wrote:
> I still sort of favor an environment stack set through a construction
> like "in env do ... end" because it gives the code on the outside control
> over whether or not the code on the inside can see or replace the
> environment itself, or only its contents. How can I restrict a chunk
> of code from interacting with _ENV directly, short of refusing to
> load source code that contains the "_ENV" name?

I'm not so sure you need to worry about restricting code from
overwriting a local _ENV any more than restricting overwriting global
functions like print.  What's the worst it can do?

The "in env do ... end" did impose a bit more structure.   In
something like "<outer code> do local _ENV = <value>; <inner code>
end", the inner code can't affect the outer environment.  However, if
you have something like "do <inner code> end; <outer code>", then the
inner code can overwrite the environment (_ENV) seen by the outer
code.  But this is really no worse than already permitted code like
"local x = <value>; do x = <value2>; print = nil end; print(x)
--changed!" if you replace x with _ENV.  It may be bad style, and I
think both are merely a case of the tendency of code with constant
variables being easier to follow and more preferred.  If Lua supported
compiler enforcement of constant bindings between lexical variables
and values (by removing the assignment statement, adding a C like
"const" qualifier, or warning on this via a linter tool), we might
write something like "local const _ENV = <value>; do <inner code> end;
<outer code>", in which case the inner code would be prohibited from
doing "_ENV = <value2>" (although as is it could still mutate the
value bound to _ENV).  Likewise, the "in env do ... end" imposed a
type of const, though as a side-effect of _ENV not even being named
and was therefore not being re-assignable nor even readable as a
first-class table, apart from the debug library.  There are advantages
to have it named (i.e. _ENV) so that we can treat it as a first-class
table and do things like f(_ENV).  Of course, nothing prevents
allowing _ENV to be both named and const: "in <value> do <inner code>
end", where the inner code is allowed to read _ENV but not assign it
like "_ENV = <value2>".  Whether that's worth the new in/do construct
and the special rule, I doubt it.