【发布时间】:2013-04-07 23:00:54
【问题描述】:
special specification of Lua's length operator 让我想知道 Lua 是否会“允许”在类似的情况下返回负值
#{[-5]=1,[-1]=3}
上面写着:
表
t的长度被定义为任何整数索引n,这样t[n]不是nil并且t[n+1]是nil;
n=-5 和 n=-1 在我的示例中符合此标准,对吧?
另外,如果
t[1]是nil,n可以为零。
对,它可以为零,但不能保证,对吧?
对于一个从 1 到给定 n 的非 nil 值的常规数组,它的长度正好是那个 n,它的最后一个值的索引。
这里不是这样,所以不适用。
如果数组有“洞”(即,
nil值介于其他非 nil 值之间),则 #t 可以是直接位于 @ 之前的任何索引987654335@ 值(也就是说,它可以将任何这样的nil值视为数组的末尾)。
这里就是这种情况,所以n=-5 和n=-1 将是有效的返回值,对吧?
我可以完全确定 Lua 总是为示例表或任何其他只包含负索引的表返回 0 吗?如果(假设)我正在编写一个 Lua 解释器并返回其中任何一个值,我会符合规范吗?
编辑
显然,Lua 的实现方式,它不会返回负值。我觉得长度运算符的文档有些不足,我看到 Lua 5.2 的文档已经改变。它现在说:
除非给出
这样的表__len元方法,否则表t的长度仅在表是序列时才定义,即其正数字键的集合等于{1..n} 表示某个整数 n。在这种情况下,n 是它的长度。请注意,像{10, 20, nil, 40}不是序列,因为它有键
4但没有键3。
所以,它现在讨论的是 positive 数字键,这更清楚了。我很聪明,但对文档并不完全满意。当它说“只有在表是序列时才定义长度”时,还应该说明即使表不是序列,也会返回一个值,但行为是未定义的。另外,这个表看起来很像一个序列:
a = setmetatable(
{0},
{
__index = function(t,k)
return k < 10 and k or nil
end
}
)
i = 1
while a[i] do
print(a[i])
i = i+1
end
--[[ prints:
0
2
3
4
5
6
7
8
9
]]
print(#a)
-- prints: 1
但是,这变得越来越挑剔,因为很明显,考虑__index 可能造成的混乱是没有意义的。 Stackoverflow 肯定不是抱怨文档可能更精确的地方。
【问题讨论】:
-
只考虑正整数索引。负数、小数和非数字索引可以包含任何内容,而不会影响
#运算符返回的长度。可能,Lua 手册应该更改为更清楚一点。 -
"... 它还应该声明即使表不是序列也会返回一个值,但 behavior 是未定义的" -- 如果行为未定义,所有的赌注都没有了,说返回一个值并不一定有意义。
标签: lua