Julia:关于变量绑定、变异和可变函数的问题

Julia: Question about variable binding, mutating, and mutable functions

我正在用 Julia 编写代码,它从一个函数 foo 中收集一些输出(它改变了它的输入参数),我试图将这个函数的递归计算附加到一个数组中 A.

例如,foo!(x) 通过向其每个元素添加 1 来更改 x 的值。

function foo!(x)
    x .= x .+ 1
    return(x)
end


julia> x = [1, 1];

julia> foo!(x);

julia> x
2-element Array{Int64,1}:
 2
 2

我想创建一个数组 A 来存储固定范围内 x = f(x) 的值。然而,A 只是最终包含 f(x) 最终值的多个副本,例如,

julia> x = [1, 1];

julia> A = [x];

julia> for i=1:3
           push!(A, foo!(x))
       end

julia> A
4-element Array{Array{Int64,1},1}:
 [4, 4]
 [4, 4]
 [4, 4]
 [4, 4]

我正在尝试让它有效地输出类似于

的东西
julia> B
4-element Array{Array{Int64,1},1}:
 [1, 1]
 [2, 2]
 [3, 3]
 [4, 4]

我无法找到有用的资源来深入理解突变,或者突变在 Julia 中的执行顺序。在这方面的任何帮助将不胜感激!

通过仅使用 push!,您只是创建了一个对单个数组(即 x)的引用的数组。这就是为什么您看到相同的值重复多次的原因。

如果您想在 foo! 的调用中保留 x 值的副本,您可以使用 copy:

julia> foo!(x) = x .+= 1
foo! (generic function with 1 method)

julia> x = [0,0];

julia> A = [copy(foo!(x)) for i in 1:4]
4-element Vector{Vector{Int64}}:
 [1, 1]
 [2, 2]
 [3, 3]
 [4, 4]

按照您编写的方式,您重复将同一对象 push! 放入 A,您的 foo! 函数会发生变异:

julia> x = [1, 1]
2-element Vector{Int64}:
 1
 1

julia> A = [x]
1-element Vector{Vector{Int64}}:
 [1, 1]

julia> foo!(x)
2-element Vector{Int64}:
 2
 2

julia> A
1-element Vector{Vector{Int64}}:
 [2, 2]

解决此问题的一种方法是在 x 发生突变之前 copy A 中的元素:

julia> for i ∈ 1:3
           A[i] = copy(x)
           push!(A, foo!(x))
       end

julia> A
4-element Vector{Vector{Int64}}:
 [1, 1]
 [2, 2]
 [3, 3]
 [4, 4]

可以找到有关值与绑定的经典读物 here