【问题标题】:Why do Julia variables not exist in the scope of for-loops?为什么 Julia 变量不存在于 for 循环的范围内?
【发布时间】:2019-01-27 02:30:51
【问题描述】:

我正在使用 Julia 进行一些基本的积分估计,并得到一个 UndefVarError 并使用以下代码:

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

错误指向第 16 行。据我了解,这意味着在 for 循环的范围内未定义 etInt。为什么 Julia 会出现这种情况?

【问题讨论】:

标签: julia


【解决方案1】:

据我了解,这意味着 etInt 在 for 循环的范围内是未定义的。

全局变量确实存在于所有局部范围内(例如 for 循环)。但是,从 Julia 版本 1.0 开始,它们在这些本地范围内是只读的。必须明确对全局变量的写访问。

举个简单的例子,而

julia> x = 1       
1                  

julia> for i in 1:3
           @show x # only reading a global variable
       end         
x = 1              
x = 1              
x = 1              

效果很好,

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

不起作用。这可以通过添加明确的global 注释来解决:

julia> for i in 1:3
           global x += 1
           @show x
       end
x = 2
x = 3
x = 4

有关详细信息,请参阅scoping section in the Julia documentation。

请注意,人们对此有很多抱怨,并且在github 和讨论区(例如here 和here)上积极讨论。

请注意,这些范围规则的影响,例如您收到的可能不直观的错误消息,只有在您在全局范围(如 REPL)中操作时才会真正影响您。如果你把所有东西都放在一个函数中——任何本地范围——你会得到预期的行为:

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

无论如何,如果全局变量几乎总是对性能不利(请参阅Performance Tips),那么您应该这样做才能真正获得快速运行时。

还要注意,在使用 IJulia 的 Jupyter 笔记本中,一切都将按预期工作。原因是人们也在想出与上下文相关的解决方案,在这种情况下是SoftGlobalScope.jl。 REPL 正在/正在考虑类似的事情。这些是人们互动工作的主要场所。

因此,总而言之,您既可以只学习范围规则(这非常简单),也可以像 jupyter 笔记本一样等待一些讨论过的“修复”。

【讨论】:

  • ... 并让我们使用“UndefVarError: x not defined”来表示这个出色的新变化......
  • 哇,这就是原因??快把我逼疯了……肯定需要一个新的错误信息
  • 最好的部分是推动!到 for 循环内的全局变量可以正常工作,所以你(即我自己)永远不会知道范围界定是问题......
【解决方案2】:

似乎 1.0 中实施的范围更改影响了 Julia 在 REPL 和笔记本上下文中的这种行为。其他一些用户对此进行了投诉,例如,

https://discourse.julialang.org/t/undefvarerror-on-loop-iterator-in-while-loop/14747 https://github.com/JuliaLang/julia/issues/28789

似乎有人提出了纠正这种奇怪现象的建议:

https://discourse.julialang.org/t/new-scope-solution/16707/

【讨论】:

    猜你喜欢
    • 2012-06-12
    • 2016-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    相关资源
    最近更新 更多