I am using Julia to do some basic integration estimation and am getting an UndefVarError with the following code:
using ExcelReaders
er = ExcelReaders
etInt = 0
waveLen = er.readxl("AM0AM1_5.xls", "Spectra!A3:A2004")
eT = er.readxl("AM0AM1_5.xls", "Spectra!B3:B2004")
gTilt = er.readxl("AM0AM1_5.xls", "Spectra!C3:C2004")
dirSol = er.readxl("AM0AM1_5.xls", "Spectra!D3:D2004")
function trArea(r::Real, l::Real, v::Array, x::Int)
return ((1/2) * (v[x] + v[x+1]) * (r-l))
end
for x in 1:length(waveLen)-1
etInt += trArea(waveLen[x], waveLen[x+1], eT, x)
end
The error points to line 16. To my understanding, this means that etInt is undefined within the scope of the for-loop. Why is this the case with Julia?
To my understanding, this means that etInt is undefined within the scope of the for-loop.
Global variables do exist in all local scopes (such as a for-loop). However, from Julia version 1.0 on they are read-only in those local scopes. Write access to global variables must be made explicit.
To give a simple example, while
julia> x = 1
1
julia> for i in 1:3
@show x # only reading a global variable
end
x = 1
x = 1
x = 1
works just fine,
julia> for i in 1:3
x += 1 # writing to a global variable
@show x
end
ERROR: UndefVarError: x not defined
Stacktrace:
[1] top-level scope at .\REPL[3]:2 [inlined]
[2] top-level scope at .\none:0
doesn't work. This can be healed by putting an explicit global
annotation:
julia> for i in 1:3
global x += 1
@show x
end
x = 2
x = 3
x = 4
For more information, see the scoping section in the Julia documentation.
Note that people have complained about this a lot and it's actively being discussed on github and discourse (e.g. here and here).
Note that the effects of these scoping rules, like the potentially unintuitive error message that you're getting, really only hit you when you operate in a global scope (like the REPL). If you put everything in a function - any local scope - you get the expected behavior:
julia> function f()
x = 1
for i in 1:3
x += 1 # no global necessary
@show x
end
nothing
end
f (generic function with 1 method)
julia> f()
x = 2
x = 3
x = 4
This is anyways what you should do to really get fast runtime as global variables are almost always bad for performance (see the Performance Tips).
Also notice that everything will work as expected in Jupyter notebooks using IJulia. The reason is that people are coming up with context dependent solutions as well, in this case SoftGlobalScope.jl. Something similar is/was being considered for the REPL. These are the main places where people work interactively.
So, to summarize, you can either just learn the scoping rules (which is dead simple) or you wait for some of the discussed "fixes" to land as has already been the case for jupyter notebooks.
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