Within a scope, an identifier may be resolved either as local or as global.
By default, if an identifier is encountered on the left-hand side of an assignment statement, its meaning is looked up in all enclosing scopes, excluding the global one (module scope), and a new binding is created if none is found. If an identifier only occurs in the right-hand sides of assignments, then it is searched for in all enclosing scopes, including the global one.
Here, you have the same identifier on both sides of an assignment. Then, the first rule takes precedence: x
does not exist in any of the enclosing local scopes, so it is local, and we must evaluate the rhs of the statement and bind x
to the result. But there is also x
in the rhs, which is undefined, so there’s an error.
Now, what to do.
a) It is perfectly fine to name local variables the same as globals, not needing to bother about the existence of a local name somewhere else in the program is one of the biggest virtues of scopes.
b) If you want to create a new variable x
and use the global x
in the same function, there’s let
to help:
function add_one()
let x_glob = x, x = x_glob .+ 1
@show x
end
end
The assignments in let
are in nested scopes, so x_glob = x
is evaluated in one scope, x = x_glob .+ 1
in another, and there’s no clash.
c) If you want to bind the global to another value, mark x
as global
anywhere in the function body:
function add_one()
x = x .+ 1
global x
@show x
end
d) If you want to mutate a global, just use some mutating function on x
as argument (like x .= x .+ 1
, as suggested by @briochemc , because it is a syntactic sugar to broadcast!
).