多重赋值是怎么工作的?

在 Lua 中的多重赋值中,Lua 会先评估所有的值,然后再执行赋值操作。因此,我们可以使用多重赋值来交换两个值,例如

x, y = y, x -- 交换 xy 的值

实际上,这个赋值是怎么工作的呢?

点赞
用户90511
用户90511

多重赋值的实现取决于您使用的 Lua 实现。只要保持语义不变,实现可以自由地按照自己的方式进行操作。也就是说,无论如何实现,您应该得到与将所有 RHS 值保存并将它们分配给 LHS 时相同的结果,就像 Lua 书中所解释的那样。

如果您仍对实际实现感到好奇,可以查看某个程序生成的字节码。例如,将以下程序

local x,y = 10, 11
x,y = y,x

传递给 Lua 5.2 的字节码编译器(luac -l)会产生以下结果

main <lop.lua:0,0> (6 instruction sat 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 来代表 xy,同时使用额外的临时寄存器为第二个槽。xy 在前两个操作符中使用常量进行初始化,在接下来的三个操作符中使用“临时”第二个槽进行交换,就像您手动操作一样:

tmp = y -- MOVE 2 1
y = x   -- MOVE 1 0
x = tmp -- MOVE 0 2

由于 Lua 在执行交换赋值和静态初始化时采用了不同的方法,因此如果进行不同类型的多重赋值(例如设置表字段),可能会得到不同的结果,特别是因为元方法会影响顺序。我们需要找到发出字节码的源代码部分才能确定 100%。正如我之前提到的,所有这些可能会因 Lua 版本和实现而异,特别是如果您将 LuaJIT 和 PUC Lua 进行比较。

2013-03-06 20:00:53