为什么Lua的长度(#)运算符返回意外值?

时间:2014-05-11 09:19:00

标签: lua

Lua有#运算符来计算"长度"用作数组的表。 我检查了这个操作员,我感到很惊讶。

这是代码,我让它在Lua 5.2.3下运行:

t = {};
t[0] = 1;
t[1] = 2;
print(#t); -- 1 aha lua counts from one
t[2] = 3;
print(#t); -- 2 tree values, but only two are count
t[4] = 3;
print(#t); -- 4  but 3 is mssing?
t[400] = 400;
t[401] = 401;
print(#t); -- still 4, now I am confused?


t2 = {10, 20, nil, 40}
print(#t2); -- 4 but documentations says this is not a sequence?

有人可以解释规则吗?

1 个答案:

答案 0 :(得分:23)

引用Lua 5.2参考手册:

  

表t的长度仅在表是序列时定义,即,对于某个整数n,其正数字键的集合等于{1..n}

#运算符对非序列的结果是 undefined 。 但是what happens in C implementation of Lua when we call # on a non-sequence

背景:Lua中的表在内部分为数组部分和散列部分。这是一个优化。 Lua试图避免经常分配内存,所以它预先分配下一个2的幂。那是另一个优化。

  1. 当数组部分中的最后一项是nil时,#的结果是通过bin搜索第一个零跟随键的数组部分找到的最短有效序列的长度。
  2. 当数组部分中的最后一项不是nil并且散列部分为空时,#的结果是数组部分的物理长度。
  3. 当数组部分中的最后一项不是nil并且哈希部分非空时,#的结果是通过bin搜索哈希部分找到的最短有效序列的长度第一个nil-follow键(即it[i] ~= nil这样的正整数t[i+1] == nil,假设数组部分充满了非nils(!)。
  4. 因此,#的结果几乎总是最短有效序列的(期望的)长度,除非表示非序列的数组部分中的最后一个元素是非零的。然后,结果是大于

    为什么?这似乎是另一个优化(对于两个幂大小的数组)。此类表格#的复杂程度为O(1),其他变体为O(log(n))