问题描述
来自 Lua 编程的第 4.1 节.
在多重赋值中,Lua 首先评估所有值,然后才执行任务.因此,我们可以使用多重赋值交换两个值,如
x, y = y, x -- 将 x' 换成
y'
x, y = y, x -- swap x' for
y'
任务实际上是如何工作的?
How does the assignment work actually?
推荐答案
多重赋值的实现方式取决于您使用的 Lua 实现.只要它保留语义,实现就可以自由地做任何它喜欢的事情.也就是说,无论事情如何实现,您都应该得到相同的结果,就像在将它们分配给 LHS 之前已将 RHS 中的所有值保存一样,正如 Lua 书籍所解释的那样.
How multiple assignment gets implemented depends on what implementation of Lua you are using. The implementation is free to do things anyway it likes as long as it preserves the semantics. That is, no matter how things get implemented, you should get the same result as if you had saved all the values in the RHS before assigning them to the LHS, as the Lua book explains.
如果您仍然对实际实现感到好奇,您可以做的一件事就是查看为某个程序生成的字节码是什么.例如,采取以下程序
If you are still curious about the actual implementation, one thing you can do is see what is the bytecode that gets produced for a certain program. For example, taking the following program
local x,y = 10, 11
x,y = y,x
并将其传递给 Lua 5.2 的字节码编译器(luac -l
)
and passing it to the bytecode compiler (luac -l
) for Lua 5.2 gives
main <lop.lua:0,0> (6 instructions at 0x9b36b50)
0+ params, 3 slots, 1 upvalue, 2 locals, 2 constants, 0 functions
1 [1] LOADK 0 -1 ; 10
2 [1] LOADK 1 -2 ; 11
3 [2] MOVE 2 1
4 [2] MOVE 1 0
5 [2] MOVE 0 2
6 [2] RETURN 0 1
MOVE 操作码将右寄存器中的值分配给左寄存器(有关详细信息,请参阅 Lua 源代码中的 lopcodes.h).显然,正在发生的事情是寄存器 0 和 1 被用于 x
和 y
并且插槽 2 被用作临时额外插槽.x
和 y
在前两个操作码中使用常量初始化,在接下来的三个 3 操作码中使用临时"第二个插槽执行交换,有点像你手工操作:
The MOVE opcode assigns the value in the right register to the left register (see lopcodes.h in the Lua source for more details). Apparently, what is going on is that registers 0 and 1 are being used for x
and y
and slot 2 is being used as a temporary extra slot. x
and y
get initialized with constants in the first two opcodes and in the next three 3 opcodes a swap is performed using the "temporary" second slot, kind of like you would do by hand:
tmp = y -- MOVE 2 1
y = x -- MOVE 1 0
x = tmp -- MOVE 0 2
鉴于 Lua 在进行交换赋值和静态初始化时如何使用不同的方法,如果您对不同类型的多重赋值得到不同的结果,我不会感到惊讶(设置表字段可能看起来非常不同,特别是从那时起,由于元方法,顺序应该很重要......).我们需要在源中找到字节码被发出的部分,以确保 100% 确定.正如我之前提到的,所有这些都可能因 Lua 版本和实现而异,特别是如果您查看 LuaJIT 与 PUC Lua.
Given how Lua used a different approach when doing a swapping assignment and a static initialization, I wouldn't be surprised if you got different results for different kinds of multiple assignments (setting table fields is probably going to look very different, specially since then the order should matter due to metamethods...). We would need to find the part in the source where the bytecode gets emitted to be 100% sure though. And as I mentioned before, all of this might vary between Lua versions and implementations, specially if you look at LuaJIT vs PUC Lua.
这篇关于多重分配如何运作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!