Lua解包错误?

我在 Lua 的 unpack 函数中遇到了一种奇怪的行为

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

第二个 unpack 函数只提供到第一个 nil 值的参数。我可以接受这样的结果。 第一个表格提供了 4 个参数,其中一个在中间为 nil。它有 4 个非 nil 参数,但它们并不是被显示的那些。

请问有人可以解释这个现象吗? 这是使用 codepad.org 和 lua 5.1 尝试的。

原文链接 https://stackoverflow.com/questions/1672985

点赞
stackoverflow用户108130
stackoverflow用户108130

2.2 - 值和类型

[...] table 类型实现了关联数组,即可以使用任何值(除了 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-04 10:59:48
stackoverflow用户173806
stackoverflow用户173806

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

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

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

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

luaB_unpack()函数使用luaL_getn(),后者的定义是基于调用lua_objlen()luaH_getn()进行的。luaH_getn()查看数组的最后一个位置,如果它是nil,则在表中执行二进制搜索以找到边界(“t[i]既不是nil,t[i + 1]是nil”)。对于数组末尾的二进制搜索是table1table2处理方式不同的原因。

如果数组中的最后一个条目为nil,那么这应该只是个问题。

来自《Lua编程》(第16页)(你应该买这本书)的解释: 当数组中有空洞(内部为nil的元素)时,长度运算符可能将这些nil元素之一假定为结尾标记。因此,您应该避免在可能包含空洞的数组上使用长度运算符。

unpack()使用长度运算符lua_objlen(),它“可能假定任何nil元素为数组的结尾”。

2009-11-04 23:18:02