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

查看:18
本文介绍了为什么 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?

谁能解释一下规则?

推荐答案

引用 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

# 运算符对非序列的结果是 undefined.但是 当我们调用 #非序列?

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时,#的结果是通过binsearch数组部分的第一个nil找到的最短有效序列的长度- 跟随键.
  2. 当数组部分的最后一项不是nil且hash部分为空时,#的结果就是数组部分的物理长度.莉>
  3. 当数组部分的最后一项不nil且hash部分不为空时,#的结果是找到的最短有效序列的长度binsearch 哈希部分的第一个 nil-followed 键(就是这样的正整数 it[i] ~= nilt[i+1] == nil),假设数组部分全是非 nil(!).
  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.

这是为什么?这似乎是又一次优化(针对二次幂大小的数组).此类表上#的复杂度为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天全站免登陆