我在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
第二个unpack传递的参数高达第一个零值。我可以忍受这个。 第一张表提供4张?参数中间有一个为零。它有4个参数不是nil,但它们不是显示的参数。
有人可以解释一下吗? 这是使用codepad.org和lua 5.1
进行的答案 0 :(得分:15)
只需将开始和结束索引指定为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
查看数组的最后一个位置,如果它是table1
,则对表中的边界执行二进制搜索(“t [i]为非零且t [i] +1]是零“)。对数组末尾的二进制搜索是table2
的处理方式与nil
不同的原因。
如果数组中的最后一个条目是unpack()
,那么这应该只是一个问题。
从Programming in Lua(第16页)(你应该买这本书。): 当一个数组有空洞 - 其中没有元素时 - 长度操作符可以将这些无元素中的任何一个作为结束标记。因此,应避免在可能包含孔的数组上使用length运算符。
lua_objlen()
使用长度运算符{{1}},“可以假设任何[nil]元素作为数组的结尾。”
答案 1 :(得分:3)
[...] 类型表实现了关联 数组,即可以的数组 索引不仅包含数字,还包括 任何值(除了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