New to Julia and hence, likely a basic question.
x = 1
function someFn()
print(x)
x = 3
end
This throws an error at print(x) because global x inside is not seen inside the function. This makes sense.
x = [1,2]
function someFn()
print(x)
x[1] = 4
end
print(x)
Here print(x) is able to see the global array x and x[1]=4 changes value of global x globally. A similar behavior is observed when I make x a dictionary.
Three questions
Let me comment on my understanding of the issue.
First, variable names point to values. The most basic way to make a binding between the variable name and the value is assignment of the form:
variable_name = value
Note that it is crucial that on the left hand side of =
the only thing that is present is variable name and nothing else.
(side note: apart from =
there are other ways to make a binding, e.g. +=
etc. or function definitions; but let us focus here on the core of the issue)
Now if you see =
this does not mean that it is an assignment that creates a new binding. In particular:
variable_name[index] = value
is not an assignment operation (that creates a new binding) but setindex!
operation. Writing variable_name[index] = value
is the same as writing setindex!(variable_name, value, index
.
(side note: this is true except for some corner cases like e.g. handling of begin
or end
, handling by @view
macro etc., but again this is not crucial in the discussion)
Now to directly answer your questions given these comments:
Is this behavior of variable / array and its scope inside a function consistent how Julia should work?
Yes. But note that you get an error in:
x = 1
function someFn()
print(x)
x = 3
end
because Julia knows that x = 3
is present in the body of the function which makes Julia aware that x
is a local variable even before it is bound to the value (a variable is either local or global).
Here is a more extreme example of the situation:
julia> x = 10
10
julia> function f()
if true
println(x)
else
x = 5
end
end
f (generic function with 1 method)
julia> f()
ERROR: UndefVarError: x not defined
although we know that the branch after else
will never executed still it makes variable x
to be local.
When x is an array, it is visible inside the function even without passing a reference as an input to function. Is this correct?
It is visible beause x[1] = 4
does not create a local variable named x
but is simply a call to setindex!
function. So there is no x
variable defined locally, therefore a global variable x
is used.
Also, changing a value of an entry in the array is reflected globally. Is this so because Julia treats array x as a reference everywhere?
Here be sure to remember that x
is not an array. It is a variable that is bound to point to an array. Then, again, x[1] = 4
is the same as if you have written setindex!(x, 4, 1)
so you simply call a function on a value (an array in this case) that a variable x
is bound to. And this works, because scoping rules in Julia say that if there is no local variable of a given name in the scope Julia searches global scope for this name.
Finally let me comment that using global variables in Julia is discouraged as this is slow. So while this discussion is highly relevant to understand how Julia works, in practice you almost never need to know this (you will use local variables 99.99% of the time, and if you use global variables better make them const
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With