I am trying to understand why using variable i inside the loop causes an issue
File main2.jl:
struct MyStruct
a::Int32
b::Int32
c::String
end
df = DataFrame( A=Int[], B=Int[] )
push!(df, [1, 10])
push!(df, [2, 20])
push!(df, [3, 30])
insertcols!(df, 3, :C => MyStruct.(Int32(0), Int32(0), ""))
insertcols!(df, 3, :D => Vector{MyStruct})
println(df)
i = 1
for r in eachrow(df)
i = i + 1
end
I get:
julia> include("main2.jl")
| A | B | D | C |
| Int64 | Int64 | DataType | MyStruct |
|-------|-------|-------------------|----------------------|
| 1 | 10 | Array{MyStruct,1} | MyStruct(0, 0, \"\") |
| 2 | 20 | Array{MyStruct,1} | MyStruct(0, 0, \"\") |
| 3 | 30 | Array{MyStruct,1} | MyStruct(0, 0, \"\") |
ERROR: LoadError: UndefVarError: i not defined
Stacktrace:
[1] top-level scope at /usr/home/.../main2.jl:19
[2] include at ./boot.jl:328 [inlined]
[3] include_relative(::Module, ::String) at ./loading.jl:1094
[4] include(::Module, ::String) at ./Base.jl:31
[5] include(::String) at ./client.jl:431
[6] top-level scope at REPL[3]:1
in expression starting at /usr/home/.../main2.jl:18
julia>
The problem is that i lives in the global scope and when you write a for loop in the global scope, it creates it's own sub-scope. You can solve the issue by changing your for loop to
i = 1
for r in eachrow(df)
global i
i = i + 1
end
However, inside function bodies, you do not need to do this (as long as i lives in the function body).
This comes down to the fact that in Julia, you often shouldnt be writing non-trivial code out in the global scope. It's considered to be proper form to put code inside functions. If the code isn't inside a function, it won't be compiled and you won't get any of the performance benefits of using Julia. More info about scoping rules can be found here: https://docs.julialang.org/en/v1/manual/variables-and-scoping/
There has been a lot of discussion over this issue and what people would rather happens instead. The discussion more or less started here: https://github.com/JuliaLang/julia/issues/28789 and then a solution was proposed here: https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/ and then now a new potential solution was discussed here: https://discourse.julialang.org/t/new-scope-solution/16707 .
It looks like currently there is no real consensus on how to change the bahaviour and so it will likely stay as is. For what it's worth, I prefer the current behaviour and think it has some advantages, though it is often surprising to newcomers.
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