11

我在 Lua 解包函数中偶然发现了一个奇怪的行为

table1 = {true, nil, true, false, nil, true, nil}
table2 = {true, false, nil, false, nil, true, nil}

a1,b1,c1,d1,e1,f1,g1 = unpack( table1 )
print ("table1:",a1,b1,c1,d1,e1,f1,g1)

a2,b2,c2,d2,e2,f2,g2 = unpack( table2 )
print ("table2:",a2,b2,c2,d2,e2,f2,g2)

输出:

table1: true    nil true    false   nil nil nil
table2: true    false   nil nil nil nil nil

第二个解包将参数传递到第一个 nil 值。我可以忍受。第一张桌子提供4?参数,中间一个为零。它有 4 个不为零的参数,但它们不是显示的参数。

谁能解释一下?这是用 codepad.org 和 lua 5.1 试过的

4

2 回答 2

17

可以简单地通过指定开始和结束索引unpack()并将其table.maxn()用作结束索引来解决该问题:

table1 = {真,无,真,假,无,真,无}

a1,b1,c1,d1,e1,f1,g1 = unpack(table1, 1, table.maxn(table1) )
打印 ("table1:",a1,b1,c1,d1,e1,f1,g1)
-->table1: true nil true false nil true nil

处理这两个表的方式存在差异的真正原因在于确定表的数组部分长度的逻辑。

luaB_unpack()函数使用which 是根据对表的哪些调用luaL_getn()定义的。查看数组的最后一个位置,如果是,则对表中的边界执行二进制搜索(“使得 t[i] 为非 nil 且 t[i+1] 为 nil”)。对数组末尾的二进制搜索是处理方式不同的原因。lua_objlen()luaH_getn()luaH_getn()niltable1table2

只有当数组中的最后一个条目是nil.

来自《Lua 编程》(第 16 页)(你应该买这本书。): 当一个数组有空洞时——里面有 nil 元素——长度操作符可以假设这些 nil 元素中的任何一个作为结束标记。因此,您应该避免在可能包含空洞的数组上使用长度运算符。

The unpack() is using the length operator lua_objlen(), which "may assume any of [the] nil elements as the end" of the array.

于 2009-11-04T23:18:02.193 回答
3

2.2 - 值和类型

[...] 类型实现了关联数组,即不仅可以用数字索引的数组,还可以用任何值(nil 除外)索引的数组。表可以是异构的;也就是说,它们 可以包含所有类型的值(nil 除外)。[...]

给定nil一个条目将破坏表枚举,并且您的变量将无法正确初始化。

这是一个简单的示例,演示了有问题的行为:

table1 = {true, false, nil, false, nil, true, nil}
for k,v in ipairs(table1) do
  print(k, v)
end

输出:

1   true
2   false
>Exit code: 0
于 2009-11-04T10:59:48.560 回答