为什么Lua的长度(#)运算符返回意外值? [英] Why does Lua's length (#) operator return unexpected values?

查看:81
本文介绍了为什么Lua的长度(#)运算符返回意外值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Lua has the # operator to compute the "length" of a table being used as an array. I checked this operator and I am surprised.

这是我在Lua 5.2.3下运行的代码:

This is code, that I let run under 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?

有人可以解释规则吗?

Can someone explain the rules?

推荐答案

引用Lua 5.2参考手册:

Quoting the Lua 5.2 Reference manual:

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

the length of a table t is only defined if the table is a sequence, that is, the set of its positive numeric keys is equal to {1..n} for some integer n

#运算符对非序列的结果为未定义. 但是当我们在Lua的非实现中调用#时,在Lua的C实现中会发生什么-序列?

The result of # operator on non-sequences is undefined. But what happens in C implementation of Lua when we call # on a non-sequence?

背景:Lua中的表在内部分为数组部分和哈希部分.这是一种优化. Lua尝试避免经常分配内存,因此它会为下一个2的幂进行预分配.那是另一种优化.

Background: Tables in Lua are internally divided into array part and hash part. That's an optimization. Lua tries to avoid allocating memory often, so it pre allocates for the next power of two. That's another optimization.

  1. 当数组部分的最后一项为nil时,#的结果为通过对数组部分进行二进制搜索以找到第一个无后继键而找到的最短有效序列的长度.
  2. 当数组部分中的最后一项不是nil并且哈希部分为空时,#的结果就是数组部分的物理长度.
  3. 当数组部分中的最后一项不是nil并且哈希部分不为空时,#的结果是通过对哈希部分进行binsearch搜索第一个nil-而找到的最短有效序列的长度.紧跟着键(即正整数i表示t[i] ~= nilt[i+1] == nil),假设数组部分中充满了non-nils(!).
  1. When the last item in the array part is nil, the result of # is the length of the shortest valid sequence found by binsearching the array part for the first nil-followed key.
  2. When the last item in the array part is not nil AND the hash part is empty, the result of # is the physical length of the array part.
  3. When the last item in the array part is not nil AND the hash part is NOT empty, the result of # is the length of the shortest valid sequence found by binsearching the hash part for for the first nil-followed key (that is such positive integer i that t[i] ~= nil and t[i+1] == nil), assuming that the array part is full of non-nils(!).

因此,除非数组部分中表示非序列的最后一个元素为非零,否则#的结果几乎总是 (最短有效序列的(期望)长度).然后,结果比期望的结果大 .

So the result of # is almost always the (desired) length of the shortest valid sequence, unless the last element in the array part representing a non-sequence is non-nil. Then, the result is bigger than desired.

那是为什么?似乎又一次优化(适用于2的幂的数组).在此类表上,#的复杂度为O(1),而其他变体为O(log(n)).

Why is that? It seems like yet another optimization (for power-of-two sized arrays). The complexity of # on such tables is O(1), while other variants are O(log(n)).

这篇关于为什么Lua的长度(#)运算符返回意外值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆