Local By Default

lua-users home

Concerns about Lua's scoping rules come up periodically on the mail list. A justification for its design would be useful here.

Lua's declarations are described as "global by default", in contrast to "local by default" (Python and Ruby). Another alternative would be for nothing to be "by default" (i.e. require explicit declarations of both locals and globals). Here are some insightful quotes on this:

[4] "Local by default is wrong. Maybe global by default is also wrong, [but] the solution is not local by default." (Roberto)

[5] "I don't really understand why anyone would want variables to be *anything* by default, as in automatic declarations. All it does is save you a few keystrokes every now and then, while opening up for endless fun looking for stupid, hard to find typo and name mixup bugs. (Assignment instead of declaration and vice versa.)" (David Olofson)

[6] "The problem is that without [explicit] local declarations, you cannot say where the variable is local to." (RiciLake)

[7] "'local by default' does not mix well with lexical scoping....Proper lexical scoping really requires that you have a choice between mutating a binding (assignment) and creating a new binding (declaration). Alas, the 'local by default' rule mixes them and makes an assignment do both." (MikePall)

[8] "It seems to me that the main argument for local-by-default, is to prevent accidents with the global environment, and secondly to make declaring locals optional, thus having to type less. Personally, I think making declarations optional is a bad idea, both for locals and for globals. To force explicit declarations for globals, as well as to prevent accidents with the global environment, I use require 'strict'. Maybe it's possible to do something equivalent (or better) at compile time. But my point is, perhaps one should ask oneself, whether one really wants/needs local-by-default, or just explicit globals declarations." (Mark Meijer)

[Python PEP 3104] -- Python's fix to "local by default", which is identical (apart from the choice of keyword!) to the proposal by ReubenThomas (see below).

[1] "[The current local variable scoping rule] is the single biggest design flaw in Ruby." (Yukihiro Matsumoto, Ruby designer) (comments: [9][10][7])

[2] -- Discussion by the various scoping rules and why the language Converge chose "local by default" with a "nonlocal" (like PEP 3104) keyword. (Laurence Tratt, Converge Designer)

[3] "I dislike the implicit declaration of lexicals because it tends to defeat the primary use of them, namely, catching typos...Declarations should look like declarations...I believe that declarations with my are properly Huffman encoded." (Larry Wall, Perl Designer)

See Also

Prior Proposal

What follows is another "local by default" proposal. IMO it's simpler, less obtrusive and yet gives better results than other proposals. (-- ReubenThomas)

The changes are:

1. Add a new keyword "outer" which works like "local", except that it declares the given name to refer to the innermost variable of the same name in an enclosing function or, if there is none, to a global of the same name (even if none currently exists).

2. The first assignment to a variable in a function implicitly acts as a "local" declaration unless it has already been declared in that function, explicitly or implicitly. Assignment outside a function works as at present, as does assignment to table elements.


a. The ability to do configuration file style global assignment is retained, at the cost of making assignment inside functions work differently from outside. In practice this shouldn't be a problem, as few Lua scripts contain complex code at the top level. If you need local variables in top-level code, you must simply declare them as at present.

b. The only change to the syntax is the addition of "outer" (similar to other proposed solutions using a "nonlocal", or "extern", or "static" keyword for declaring these uses of symbols not defined in the lexical scope or in any closure).

c. The only semantic change is to the meaning of assignment within functions.

d. Assignments only make the variable local where they occur, rather than for the whole function. This agrees with the principle of least surprise: you don't have to read an entire function to find out whether a given variable is local (and nor does the compiler, so the implementation is simple).

RecentChanges · preferences
edit · history
Last edited June 2, 2020 3:14 pm GMT (diff)