I am using Julia 1.6.1:
julia> VERSION
v"1.6.1-pre.1"
I find the local scope rules are confusing to apply to inner scopes (such as inner functions). The rules are described at described at Scope of Variables · The Julia Language and copied below:
-
Existing local: If
x
is already a local variable , then the existing localx
is assigned; -
Hard scope: If
x
is not already a local variable and assignment occurs inside of any hard scope construct (i.e. within a let block, function or macro body, comprehension, or generator), a new local namedx
is created in the scope of the assignment; -
Soft scope: If
x
is not already a local variable and all of the scope constructs containing the assignment are soft scopes (loops,try
/catch
blocks, orstruct
blocks), the behavior depends on whether the global variablex
is defined:
-
a. if global
x
is undefined , a new local namedx
is created in the scope of the assignment; -
b. if global
x
is defined , the assignment is considered ambiguous:- i. in non-interactive contexts (files, eval), an ambiguity warning is printed and a new local is created;
-
ii. in interactive contexts (REPL, notebooks), the global variable
x
is assigned.
Now, consider this example:
function funout()
global x = 1
function funin()
x = 2
end
funin()
return x # x is global variable
end
Here, the inner function funin()
creates a hard scope. The assignment x = 1
before the definition of funin()
is global (not local), so I thought the assignment x = 2
inside funin()
would create a new local variable according to Rule 2 above. However, executing funout()
actually updates the global variable:
julia> funout()
2
julia> x # global variable
2
Consider another example:
function myfun()
global x = 1
for i = 1:3
x = i
end
return x
end
Here, the for
loop inside the function myfun()
creates a soft scope. Again, the assignment x = 1
before the for
loop is global (not local). Therefore, the above definition of myfun()
is put in a file and and executed, I thought Rule 3.b.i would apply. However, neither an ambiguity warning is generated, nor the assignment x = i
in the for
loop creates a new local variable:
julia> code = """function myfun()
global x = 1
for i = 1:3
x = i
end
return x
end
myfun()
""";
julia> include_string(Main, code)
3
julia> x # global variable
3
Based on these examples, I feel that something is missing from the description of the local scope rules in the documentation. Are there any exceptions to the rules related to the inner scopes or the usage of the global
keyword?
UPDATE. I realized that Rule 3 applies when all the scopes enclosing the assignment are soft scopes. So Rule 3.b.i does not apply to the second example because myfun()
is a hard scope. But then, the local scope rules don’t seem to specify what happens to the assignment inside a soft scope enclosed by a hard scope.