我试图理解为什么i
在循环内使用变量会导致问题
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
我得到:
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>
问题在于,它i
存在于全局范围内,当您在全局范围内编写for
循环时,它将创建自己的子范围。您可以通过将for
循环更改为
i = 1
for r in eachrow(df)
global i
i = i + 1
end
但是,在功能体内,您无需执行此操作(只要i
生活在功能体内)。
这归结为一个事实,在Julia中,您通常不应该在全局范围内编写非平凡的代码。将代码放入函数内部被认为是适当的形式。如果代码不在函数内,则将不会对其进行编译,并且不会获得使用Julia的任何性能好处。有关作用域规则的更多信息,请参见:https : //docs.julialang.org/en/v1/manual/variables-and-scoping/
关于这个问题已经有很多讨论,而人们宁愿发生什么。讨论或多或少从这里开始:https : //github.com/JuliaLang/julia/issues/28789,然后在这里提出了解决方案:https : //discourse.julialang.org/t/another-possible-solution-to -the-global-scope-debacle /,然后在这里讨论一个新的潜在解决方案:https : //discourse.julialang.org/t/new-scope-solution/16707。
似乎目前尚无关于如何更改行为的真正共识,因此可能会保持不变。对于它的价值,我更喜欢当前的行为,并认为它具有一些优点,尽管对于新手来说通常令人惊讶。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句