Julia 函数内字典值的重新分配

Sun*_*dar 5 arrays dictionary scope function julia

Julia 的新手,因此,可能是一个基本问题。

x = 1
function someFn()
   print(x)
   x = 3 
end
Run Code Online (Sandbox Code Playgroud)

这会在 print(x) 处引发错误,因为在函数内部看不到全局 x 内部。这是有道理的。

x = [1,2]
function someFn()
   print(x)
   x[1] = 4
end
print(x)
Run Code Online (Sandbox Code Playgroud)

这里 print(x) 能够看到全局数组 x 并且 x[1]=4 全局更改全局 x 的值。当我制作 xa 字典时观察到类似的行为。

三问

  1. 变量/数组的这种行为及其在函数内的作用域是否与 Julia 的工作方式一致?
  2. 当 x 是一个数组时,即使没有将引用作为输入传递给函数,它在函数内部也是可见的。这样对吗?
  3. 此外,更改数组中条目的值会全局反映。这是因为 Julia 将数组 x 视为无处不在的引用吗?

Bog*_*ski 3

我来说说我对这个问题的理解。

首先,变量名指向值。在变量名和值之间建立绑定的最基本方法是以下形式的赋值:

variable_name = value
Run Code Online (Sandbox Code Playgroud)

请注意,至关重要的是,左侧=唯一存在的是变量名称而没有其他内容。

(旁注:除了=还有其他方法可以进行绑定,例如+=等或函数定义;但让我们在这里关注问题的核心)

现在,如果您看到=这并不意味着它是创建新绑定的赋值。尤其:

variable_name[index] = value
Run Code Online (Sandbox Code Playgroud)

不是赋值操作(创建新绑定)而是setindex!操作。写作variable_name[index] = value与写作是一样的setindex!(variable_name, value, index

(旁注:除了一些极端情况之外,这是正确的,例如处理beginor end、通过@view宏处理等,但这在讨论中并不重要)

现在根据这些评论直接回答您的问题:

变量/数组的这种行为及其在函数内的作用域是否与 Julia 的工作方式一致?

是的。但请注意,您会收到以下错误:

x = 1
function someFn()
   print(x)
   x = 3 
end
Run Code Online (Sandbox Code Playgroud)

因为 Julia 知道它x = 3存在于函数体中,这使得 Juliax甚至在它绑定到值之前就知道它是一个局部变量(变量是局部变量或全局变量)。

这是情况的一个更极端的例子:

julia> x = 10
10

julia> function f()
       if true
           println(x)
       else
           x = 5
       end
       end
f (generic function with 1 method)

julia> f()
ERROR: UndefVarError: x not defined
Run Code Online (Sandbox Code Playgroud)

尽管我们知道之后的分支else永远不会执行,但它仍然使变量x成为本地变量。

当 x 是数组时,即使不将引用作为函数的输入传递,它在函数内部也是可见的。它是否正确?

这是可见的,因为x[1] = 4没有创建名为的局部变量x,而只是对setindex!函数的调用。因此没有本地定义的变量,因此使用x全局变量。x

此外,更改数组中条目的值也会全局反映。这是因为 Julia 在任何地方都将数组 x 视为引用吗?

这里一定要记住x不是数组。它是一个绑定指向数组的变量。然后,再次x[1] = 4与您编写的内容相同setindex!(x, 4, 1),因此您只需对变量绑定到的值(在本例中x为数组)调用函数即可。这是可行的,因为 Julia 中的作用域规则规定,如果作用域中没有给定名称的局部变量,则 Julia 会在全局作用域中搜索该名称。

最后让我评论一下,不鼓励在 Julia 中使用全局变量,因为这很慢。因此,虽然这个讨论与理解 Julia 的工作原理高度相关,但在实践中你几乎不需要知道这一点(99.99% 的时间你都会使用局部变量,如果你使用全局变量就更好了const)。