Hello guys! In test1, array A has a local scope, shouldn’t it be global? In test2, array A has a global scope (OK). That seems wrong to me. Both scopes must be global. The difference in the two situations is very subtle! Please help me to understand correctly.
A = [1,2,3]
function test1()
println("test1")
A = [4,5,6] # can't take global ref
end
test1()
println(A) # = [1, 2, 3]
function test2()
println("test2")
A[1:end] = [4,5,6] # catch global ref, global A = [4,5,6] # It also works
end
test2()
println(A) # = [4, 5, 6]
Julia Version 1.6.0
Commit f9720dc2eb (2021-03-24 12:55 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Core™ i3-7020U CPU @ 2.30GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-11.0.1 (ORCJIT, skylake)
Hi. The rules are applied correctly: In the first example you assign a new object to the variable A the first time it is seen, and that makes it a local variable. In the second example you modify the variable A the first time it is seen; that’s partly a “read” operation, because you access its contents to select what part of the array must be replaced, so it is assumed to be a global.
I really recommend reading Manual > Scope of Variables > Local Scope, or even the whole Scope of variables section. Also, note there may be small differences on how scope behave based on if you are executing the code in the REPL or from a file.
If you want to use a global variable, you have to do that. But you should not do that almost never, because that hurts performance a lot. See the performance tips, the first one!
You should pass the variables as arguments to your function, i. e.
A = [1,2,3]
function test(A)
println(A)
end
julia> test(A)
[1, 2, 3]
In addition to the advice given by @lmiq, if what you want is to update the values of A, while keeping the type of its elements and also its size, you can proceed as in your second example, but a nicer way of doing it – without indexing – is:
A = [1,2,3]
function test()
A .= [4,5,6] # note that it is a "dotted assignment"
end
The “dotted assignment” means “replace the elements of A by the elements of the right hand side”, in contrast to = that means “replace the whole object referred to by A by the object on the right hand side”. That doesn’t have the downside of modifying globals mentioned before.
Global variables are good essentially to represent effectively constant values, like the speed of light. In which case declare them as constant globals:
const c = 299792458
This you can use inside a function without performance problems, but you cannot modify it* (you can, but that is another story, normally you should not and the standard behaviour and errors reflects that).
“right” may mean many things. What I meant is that you can use a global constant variable in good code, and that will perform well and also be easy to understand and predictable.
One other reason for not using non-constant global variables is that their values can change and so the result of a function can be unpredictable. For example:
function f(x)
return x + a
end
what does this function return? That depends on what a is. If a is a trully constant value defined in your code, like the speed of light, declared as const a = ..., then someone will be able to predict the result of the function (and the compiler will know everything that it need about the function to optimize it). If a is not a constant, it may change depending on the definition of a provided at runtime. Then the result of f is unpredictable, and the code is hard to understand and to debug, and also the compiler cannot do optimizations.
That’s right, I have. I use include(“program.jl”) because of PyPlot, because the first run of the plot is very long and I have to test the code several times. Then, when there are constants in the global scope, Julia keeps giving me warnings, so I change constants to variables! Another thing that I think is bad is passing too many parameters in functions in several functions.
But, if if you are plotting stuff only, you can do everyting in global scope just fine. The peformance tips are important for code that needs performance. Otherwise one can use the flexibility of the dynamic typing as one wants.