英文:
Chained variable assignment in Julia
问题
我对Julia如何处理以下代码块感到困惑:
a = [1,2,3]
a .= a/2 .= o = a .* 2
对于'a'和'o'的输出都是[2,4,6]。然而,我不明白为什么'a'的结果与我使用a .= a*2
的结果相同。a/2
被视为变量并传递给数组[2,4,6]
(即a*2
的结果)吗?然后这个“变量”a/2
被传递给a
吗?我本来希望a
保持为[1,2,3]
。我不确定Julia是否以特定顺序执行这些操作。
英文:
I'm puzzled by how Julia handles the block of code below:
a = [1,2,3]
a .= a/2 .= o = a .* 2
The output for both 'a' and 'o' is [2,4,6]. However, I don't understand why the result for 'a' is the same as if I had used a .= a*2
. Is a/2
treated as a variable and passed the array [2,4,6]
(the result of a*2
)? And then this "variable" a/2
is passed to a
? I would have expected a
to have stayed as [1,2,3]
. I'm uncertain as to whether Julia executes these operations in a specific order.
答案1
得分: 2
表达式 a / 2
创建了一个新的数组,最初包含您期望的值 ([1,2,3]
),然而,该数组的内容立即被右侧数组的广播赋值所覆盖。
让我们分解整个表达式,Julia 可以帮助我们:
julia> :(a .= a/2 .= o = a .* 2)
:(a .= (a / 2 .= (o = a .* 2)))
通过查看在打印 Expr
时插入的括号,我们可以更清楚地看到子表达式。正如您所看到的,顶部表达式是 a .= (右侧所有内容的结果)
。
让我们在 REPL 中对其进行评估:
julia> o = a .* 2
3-element Vector{Int64}:
2
4
6
julia> a / 2 .= (o = a .* 2)
3-element Vector{Float64}:
2.0
4.0
6.0
julia> a .= (a / 2 .= (o = a .* 2))
3-element Vector{Int64}:
2
4
6
正如您所看到的,由 a / 2
创建的数组是 Float64 数组,因此在放入 a
时被转换成 Int64,然后再次转换回来。
我们可以通过使用 Meta.show_sexpr
使右侧表达式更加明确。
julia> :(a/2 .= o = a .* 2) |> Meta.show_sexpr
(:.=, (:call, :/, :a, 2), (:(=), :o, (:call, :.*, :a, 2)))
让我们为清晰起见添加一些空格:
(:.=,
(:call, :/, :a, 2),
(:(=),
:o,
(:call, :.*, :a, 2)))
因此,此表达式是将值广播分配给调用参数 a
和 2
上的 /
函数返回的值。分配的值是赋值 o = a * 2
返回的值。
英文:
The expression a / 2
creates a new array which initially contains the values you expect ([1,2,3]
) however the contents of that array are immediately overwritten by a broadcast assignment with the contents in the right hand side array.
Let's break down the entire expression, Julia can help us:
julia> :(a .= a/2 .= o = a .* 2)
:(a .= (a / 2 .= (o = a .* 2)))
By looking at the parentheses inserted when the Expr
is printed we see the subexpressions a bit more clearly. As you can see the top expression is a .= (result of everything on RHS)
.
Let's evaluate it in the REPL:
julia> o = a .* 2
3-element Vector{Int64}:
2
4
6
julia> a / 2 .= (o = a .* 2)
3-element Vector{Float64}:
2.0
4.0
6.0
julia> a .= (a / 2 .= (o = a .* 2))
3-element Vector{Int64}:
2
4
6
As you can see the array created by a / 2
is a Float64 array and the values are therefore converted and then converted back to Int64 when put into a
.
We can make the right hand side expression even more explicit by using Meta.show_sexpr
.
julia> :(a/2 .= o = a .* 2) |> Meta.show_sexpr
(:.=, (:call, :/, :a, 2), (:(=), :o, (:call, :.*, :a, 2)))
let's add some whitespace for clarity:
(:.=,
(:call, :/, :a, 2),
(:(=),
:o,
(:call, :.*, :a, 2)))
so this expression is broadcast assigning to the value that is returned by calling the /
function on the arguments a
and 2
. The value that is assigned is what the assignment o = a * 2
returns.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论