【问题标题】:Might Lua's length operator return a negative index?Lua 的长度操作符会返回一个负数吗?
【发布时间】: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=-5n=-1 在我的示例中符合此标准,对吧?

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

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

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

这里不是这样,所以不适用。

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

这里就是这种情况,所以n=-5n=-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


【解决方案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 &gt;= ilen(xs) - 请参阅the ltable.c source 中 luaH_getn 的定义。但是规范现在故意不承诺这种行为:符合规范的实现可以返回 nil 或引发异常以尝试查找非序列表的长度。

【讨论】:

    【解决方案2】:

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

    我认为你混淆了一个事实,即如果找到 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.
    

    【讨论】:

    • 按照这个逻辑,如果我在索引 100 处找到 nil,那么作为实现者,我将被允许返回 99。这显然不准确。
    • 这不是暗示的吗?因为如果您在 100 处找到 NIL,则 return 将为 99,这满足以下“表 t 的长度被定义为任何整数索引 n 使得 t[n] 不是 nil 并且 t[n+1] 是无”
    • 不,不是,因为对于n=99 t[n] nil,但要求它是不是 @ 987654326@.
    • 这不是你在上面的引用中写的:“按照这个逻辑,如果我在索引 100 处找到一个 nil,那么作为实现者,我将被允许返回 99”,即 n=99 和n+1 是 100
    • 是的,这是作为您答案逻辑的示例(据我了解)。我认为你的逻辑是相反的。很明显,最后一个索引后面的索引应该返回 nil,但是 Lua 没有最后一个索引的真正概念,它使用这个引用的逻辑来确定表的长度,并且对于具有相同内容的表可以得出不同的结论。你可以去here,粘贴这段代码,看到内容是一样的,但首先确定的长度是3,然后是1:a={1,nil,3} print(a[1],a[2],a[3],#a) a={1,[3]=3} print(a[1],a[2],a[3],#a)
    猜你喜欢
    • 2014-06-28
    • 2016-08-19
    • 2012-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-28
    • 2019-07-13
    • 1970-01-01
    相关资源
    最近更新 更多