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.
Description: S/MIME cryptographic signature