定义变量时,Julia 会抛出未定义的错误

Julia throws undefined error when the variable is defined

我有一个使用 i = 1 作为索引的简单 while 循环。

global i = 1 
    
    n = rows
    while i <= n
        if prod(isa.(collect((y)[i,:]),Number))==0
            delete!(y,i)
            x_axis = x_axis[1:end .!= i]
            n -= 1
        end
        i += 1
    end

但我收到此错误:

UndefVarError: i not defined

top-level scope@Local: 23

我什至按照关于 SO 上一些类似问题的建议将我的 i 设为全局,但错误仍然存​​在。我在 Pluto.jl 上 运行,所以可能是环境问题。

首先,请注意,如果您使用 Julia v1.5+,那么您 不需要i 设为全局(下面的示例使用当前稳定版本 v1 .5.4):

julia> i = 1
1

julia> while i < 5
           println(i)
           i += 1     # <----- this works in Julia v1.5+
       end
1
2
3
4

但是,您似乎使用的是旧版本的 Julia v1.4,在这种情况下,我认为 Logan Kilpatrick 给了您答案:您需要从 inside[ 中将 i 设为全局变量 while 循环的作用域。正如 Logan 所提到的,尝试在增加 i 的地方添加 global,就像 while 函数文档中的这个例子:

julia> i = 1 ;

julia> while i < 5
           println(i)
           global i += 1     # <------------ Try this!
       end
1
2
3
4

另请注意,如果您的 while 循环在函数内部,您 不需要 指定它是全局的,如

julia> function foo(istart)
           i = istart
           while i < 5
               println(i)
               i += 1     # <-- 'global' not needed inside a function!
           end
       end
foo (generic function with 1 method)

julia> foo(1)
1
2
3
4

您遇到了“模棱两可的软范围案例”。

简而言之:局部变量在(软)局部范围内的赋值取决于代码是否在“REPL 上下文”中 与否。

例如,对于“REPL 上下文”,我指的是 REPL 和在这种情况下表现为 REPL 的所有环境 木星:

julia> i = 0
julia> while i < 3
         i += 1
         @info i
       end
[ Info: 1
[ Info: 2
[ Info: 3

取而代之的是来自文件、eval 和 Pluto 等非交互式上下文的代码,其行为如下:

julia> code = """
       i = 0
       while i < 3
         i += 1
         @info i
       end
       """

julia> include_string(Main, code)
┌ Warning: Assignment to `i` in soft scope is ambiguous because a global variable by the same name exists: `i` will be treated as a new local. Disambiguate by using `local i` to suppress this warning or `global i` to assign to the existing global variable.
└ @ string:3
ERROR: LoadError: UndefVarError: i not defined

所有这些都旨在确保 REPL 使用的便利性,并避免大规模使用 julia 带来的不良副作用。

完整详情here

要解决此问题,您可以按照已建议的方式使用 global 或将您的代码包含在一个函数中。

Pluto 将单元格隐式包装到函数中,请参阅 https://github.com/fonsp/Pluto.jl/pull/720,因此不需要 global 注释或显式包装到函数中。

将以下内容放入 Pluto 单元格对我有用:

begin
    i = 1
    n = 100
    while i<=n
        if i % 2 == 0
            n -= 1
        end
        i += 1
    end
end

当在单元格内使用宏时,隐式函数包装被禁用(这会阻止 Pluto 收集反应性信息),因此由于 Julia 作用域规则,以下内容在 Pluto 中不起作用:

begin
    i = 1
    n = 100
    while i<=n
        if i % 2 == 0
            n -= 1
        end
        @show i += 1
    end
end

投掷:

UndefVarError: i not defined

top-level scope@Local: 5[inlined]
top-level scope@none:0