为什么Julia变量在for循环范围内不存在?

jka*_*ros 3 julia

我正在使用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
Run Code Online (Sandbox Code Playgroud)

错误指向第16行。据我所知,这意味着在for循环范围内未定义etInt。朱莉娅为什么会这样?

crs*_*nbr 5

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

全局变量确实存在于所有局部范围内(例如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              
Run Code Online (Sandbox Code Playgroud)

效果很好

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
Run Code Online (Sandbox Code Playgroud)

不起作用。可以通过放置显式global注释来治愈:

julia> for i in 1:3
           global x += 1
           @show x
       end
x = 2
x = 3
x = 4
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参见Julia文档中范围界定部分

请注意,人们对此抱怨很多,并且正在github和讨论中对此进行积极讨论(例如herehere)。

请注意,这些作用域规则的影响(例如,您收到的可能不直观的错误消息)实际上仅在全局范围内运行时才受到打击(例如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
Run Code Online (Sandbox Code Playgroud)

无论如何,这是您要真正获得快速运行时间应该采取的措施,因为全局变量几乎总是对性能不利(请参阅“ 性能提示”)。

还要注意,所有使用IJulia的Jupyter笔记本电脑都可以按预期工作。原因是人们也提出了上下文相关的解决方案,在本例中为SoftGlobalScope.jl。REPL正在/正在考虑类似的事情。这些是人们进行交互工作的主要场所。

因此,总而言之,您可以只学习作用域定义规则(这是非常简单的),也可以等待一些讨论过的“修复程序”着陆,就像Jupyter笔记本电脑一样。