Lua 的长度操作符会返回负索引吗?

Lua 中的长度运算符具有特定规范,这让我想知道在以下情况下 Lua 是否会“允许”返回负值:

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

参考文献如下:

t 的长度定义为任何整数索引 n,满足 t [n] 不是 nilt [n + 1] 是 **nil**。

在我的示例中,n=-5n=-1 符合此条件,对吧?

另外,如果t[1]是**nil**,则可以为零。

没错,它_可以_是零,但不能保证,对吧?

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

这在这里不适用,因此不适用。

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

在这里是这样的,所以 n=-5n=-1再次是有效的返回值,对吧?

我是否可以确定 Lua 对示例表,或者包含仅为负索引的任何其他表都返回 0?(假设我将编写一个 Lua 解释器并且要返回其中之一的值,是否符合规格?

编辑

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

除非给出 __len 的元方法,否则仅当表是一个 _sequence_(即,其正数数值键的集合等于一些整数 n 的 {1..n})时,才定义表 t 的长度。在这种情况下,长度为 _n_。请注意,像下面这样的表

  {10, 20, nil, 40}

不是序列,因为它具有键 4,但没有键 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 显然不是抱怨可能更精确的文档的地方。

点赞
用户1896367
用户1896367

从参考链接中的文本来看,答案是否定的。

我认为你混淆了一个事实,即如果找到一个NIL,则被认为表的长度是找到NIL的位置-1。

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

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

表t的长度定义为任何整数索引n,使得t[n]不是nil且t[n+1]是nil; 此外,如果t(1)为nil,则n可以为零。
2013-04-15 18:38:11
用户222815
用户222815

正如你所注意到的,长度运算符的规范在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) - 查看ltable.c源代码luaH_getn方法的定义。但是现在规范没有保证这种行为:符合规范的实现可以返回nil或者抛出异常,当尝试寻找非序列表的长度时。

2013-05-01 22:21:33