I have an alternate, non-breaking solution to the scope issue previously discussed on discourse and github. The new potential solution is the following rule to decide whether a variable,
x, which is not marked as explicitly
glogal and which is assigned to in a top-level scope construct is local or global:
xis global if it is accessed before being assigned on all paths through the scope body.
In other words,
x is local unless there’s no way it could make sense for it to be local. Or, in compiler lingo,
x is local unless every assignment to
x is dominated by an access.
This solution fixes the various examples that people have complained about, since in all of these, the global variable is used as an accumulator and is read before being modified. For example:
t = 0 for i = 1:10 t += i end # expect `t == 55` here
t += i means
t = t + i and
t is accessed before being updated, the
t in the for loop body refers to the global
t rather than a local
t. Or, more simply put,
t is global because otherwise there’s no way this code could not be an error.
- Solves the problematic cases that people have complained about.
- Non-breaking: any code whose behavior changes would previously have resulted in an error. We consider such a change to be “minor” in the sense discussed in this thread.
- The default is still that variables in local scopes are local. This avoids accidentally littering global scope with variables that are only used within each iteration of a loop.
- Top-level behavior roughly approximates behavior inside of functions. It’s not perfect, but it’s much better than what we have now and possibly better than what we had before (≤ 0.6).
- Statically resolvable: the meaning of code does not depend on what global variables exist.
- The only downside it seems to have is that it’s a bit subtle and rather DWIMy.