使用下标和线性索引分配给数组的 Julia 语言问题

m20*_*022 4 arrays indexing julia

来自 R,我对 Julia 语言比较陌生。

有时我会遇到这样一种情况,我想在同一个命令中使用两次索引:首先使用一组下标,然后使用线性索引。如:

array = zeros(3, 3, 3)
array[:, :, 2][9] = 999
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,朱莉娅通过返回答案来回应:

julia> array[:, :, 2][9] = 999
999
Run Code Online (Sandbox Code Playgroud)

但是,原始数组不变:

julia> array[:, :, 2]
3×3 Array{Float64,2}:
 0.0  0.0  0.0
 0.0  0.0  0.0
 0.0  0.0  0.0
Run Code Online (Sandbox Code Playgroud)

这是一个错误,还是有一些关于我缺少的语言的事实来解释它为什么会这样?

mca*_*ott 5

简答

@views array[:, :, 2][9] = 999
Run Code Online (Sandbox Code Playgroud)

更多细节

这里要知道的是,无论是什么,它都x[1] = y被降低为对 的单个函数调用。这是一个普通函数,因此它的所有参数都在调用该函数之前进行评估。您可以通过以下方式查看正在执行的操作:setindex!x

julia> set1(x) = x[1] = 33
set1 (generic function with 1 method)

julia> @code_lowered set1(zeros(3))
CodeInfo(
1 ?     Base.setindex!(x, 33, 1)
???     return 33
)

julia> :( z[1,:][2] ) # the brackets show precedence, else try |> dump
:((z[1, :])[2])

julia> set2(z) = z[1,:][2] = 3^4;

julia> @code_lowered set2(zeros(2,3))
CodeInfo(
1 ? %1 = Core.apply_type(Base.Val, 4)
?   %2 = (%1)()
?   %3 = Base.literal_pow(Main.:^, 3, %2)
?   %4 = Base.getindex(z, 1, Main.:(:))
?        Base.setindex!(%4, %3, 2)
???      return %3
)
Run Code Online (Sandbox Code Playgroud)

Whenx是另一个索引表达式,这只是函数调用getindex(z,1,:)。这会创建一个副本,并setindex!写入副本,然后返回其右侧(临时变量%3,包含3^4)。副本永远不会逃脱。

获得您想要的行为的方法是x通过编写view(z,1,:)[2] = 33或创建视图而不是副本:

julia> set3(z) = @views z[1,:][2] = 33;

julia> @code_lowered set3(zeros(2,3))
CodeInfo(
1 ? %1 = (Base.maybeview)(x, 1, Main.:(:))
?        Base.setindex!(%1, 33, 2)
???      return 33
)

julia> z3 = zeros(2,3);

julia> set3(z3)
33

julia> z3
2×3 Matrix{Float64}:
 0.0  33.0  0.0
 0.0   0.0  0.0
Run Code Online (Sandbox Code Playgroud)

肯定可以降低z[1,:][2] = 3到其他东西,比如multi_setindex!(z, 3, (1,:), (2,))也许是某种功能。我想这被认为过于复杂。

我认为 R 具有非标准评估,在这种评估下,函数可以在评估之前访问其参数,但 Julia 不允许这样做。它确实有宏(总是用 表示@),可以在计算之前对输入语法进行操作。这是@views工作所必需的,当然也是@code_lowered为了看到33或以外的东西9