|
Sorry to raise the issue of implicit globals yet again. The
trouble is that Lua is such an elegantly designed language that this one little
imperfection keeps nagging away at one! Roberto recognises the problem in “Programming
in Lua” and suggests a few run-time fixes. However I would like to
suggest a compile-time fix which might solve the problem more elegantly. At the moment, when the statement “x = x” (this
is a contrived example for illustration, I mean any variable reference except
in a local statement) is compiled, the two references to ‘x’ are
resolved by first checking as a local variable, then as an upvalue and as a
last resort compiling the statement as “getfenv()[‘x’] = getfenv()[‘x’]”
which postpones resolution to run-time. This gives the behaviour of implicitly
creating a global variable unless it is explicitly declared, somewhere in the
lexical containment structure, as local. My suggestion is that the compiler should continue to
resolve *access* reference as it does at the moment, but *assignment*
reference should be changed. As currently, first ‘x’ would be
checked as a local and then as an upvalue, but if this does not resolve it
would be created as a local. So in effect “x = x”, when ‘x’
has not already been declared, would be compiled as “local x = getfenv()[‘x’]”.
To assign to or create a global variable one must now write, for example, “_G.x
= x”. However note that one can still *access* a global variable
without the prefix, so library functions and modules are not broken. This suggestion simplifies the language by eliminating the “local”
keyword (except for the esoteric case of overriding an upvalue), regularises it
by lexically scoping variables by default and solves the issue of accidental
pollution of the global namespace without requiring “option explicit”
or run-time protection mechanisms. “Naive” code will tend to be
more efficient since chunk-level locals resolved at compile-time will intuitively
replace globals resolved at run-time. Furthermore backward compatibility is
maintained in most everyday cases, probably only breaking some module or
library files. A directive could be provided to ease transition by specifying
old or new behaviour for a given compilation chunk. If this is controversial, could it maybe be considered as a
patch, compile time, or “C” API switch so it could be experimented
with prior to a decision on final adoption? However, unless I’ve missed
something, I cannot see any serious downside with this solution, except of
course for migration issues. |
Attachment:
smime.p7s
Description: S/MIME cryptographic signature