3

Lua 的长度运算符的特殊规范让我想知道 Lua 是否会“允许”在类似的情况下返回负值

#{[-5]=1,[-1]=3}

它说:

表的长度t定义为任何整数索引n,例如t[n]is notnilt[n+1]is nil

n=-5n=-1在我的例子中会满足这个标准,对吧?

此外,如果t[1]niln则可以为零。

对,它可以为零,但不能保证,对吧?

对于从 1 到给定 n 的非 nil 值的常规数组,它的长度正好是 n,它的最后一个值的索引。

这不是这里的情况,所以它不适用。

如果数组有“洞”(即nil其他非 nil 值之间的值),那么 #t 可以是任何直接在nil值之前的索引(也就是说,它可以将任何这样nil的值视为数组的末尾)。

这里就是这种情况,所以再次,n=-5并且n=-1将是有效的返回值,对吗?

我可以完全确定 Lua 总是为示例表或任何其他只包含负索引的表返回 0 吗?如果(假设)我正在编写一个 Lua 解释器并返回其中任何一个值,我会符合规范吗?

编辑

显然,Lua 的实现方式,它不会返回负值。我觉得长度运算符的文档有些不足,我看到 Lua 5.2 的文档已经改变。它现在说:

除非__len给出元方法,否则t只有当表是一个序列时才定义表的长度,也就是说,对于某个整数n,其正数字键的集合等于{1..n}。在这种情况下,n是它的长度。请注意,像

  {10, 20, nil, 40}

不是序列,因为它有 key4但没有 key 3

所以,它现在谈论的是数字键,这就更清楚了。我很聪明,但对文档并不完全满意。当它说“只有在表是序列时才定义长度”时,它还应该说明即使表不是序列也会返回值,但行为是未定义的。此外,这个表看起来很像一个序列:

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 肯定不是抱怨文档可能更精确的地方。

4

2 回答 2

1

正如您所注意到的,长度运算符的规范在 5.1 和 5.2 之间发生了变化。

我可以完全确定 Lua 总是为示例表或任何其他只包含负索引的表返回 0 吗?

您可以为当前的参考实现,这确保为ilen定义

function ilen (xs) 
    local i=0
    while xs[i+1] do i=i+1 end
    return i 
end

我们总是有-源代码#xs >= ilen(xs)中查看 luaH_getn 的定义。但是规范现在故意不承诺这种行为:一致的实现可以返回或引发异常,以尝试查找不是序列的表的长度。ltable.cnil

于 2013-05-01T22:21:33.203 回答
0

来自参考链接中的文本。答案是不。

我认为您令人困惑的是,如果找到 NIL,则表的长度被认为是找到 NIL 的位置-1。

因此,如果 t(1) 为 NIL,则 1 - 1 = 0,因此表长度为 0。

如果表的长度为 5,则下一个位置或 t(6) 为或将为零

The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t[1] is nil, n can be zero.
于 2013-04-15T18:38:11.607 回答