Lua表中的'nil'作为一个元素?

5

我想知道在Lua中,nil是否是一个有效的表元素。

我不明白的是:

下面的代码会打印出3

t = {1, 2, 3, nil};
print(#t);

但是以下代码会输出4
t = {1, nil, 3, 4};
print(#t);

我不明白为什么这两段代码会有不同的输出结果。

2
可能是 如何在表中表示 nil 的重复问题。 - James Whyte
使用 t = table.pack(1, 2, 3, nil) print(t.n) - Henri Menke
3个回答

4
你所遇到的是参数修剪。
我们来看一下你所拥有的内容,并解释Lua解析时发生的情况。
-- T is equal to 1, 2, 3, (NOTHING)
-- Therefore we should trim the nil from the end.
t = {1, 2, 3, nil};

-- T is equal to 1, nil, 3, 4
-- We have something on the end after nil, so we'll count nil as an element.
t = {1, nil, 3, 4};

同样的情况在函数中也会发生。这可能有点麻烦,但有时很方便。以以下代码为例:
-- We declare a function with x and y as it's parameters.
-- It expects x and y.
function Vector(x, y) print(x, y); end

-- But... If we add something unexpected:
Vector("x", "y", "Variable");
-- We'll encounter some unexpected behaviour. We have no use for the "Variable" we handed it.
-- So we just wont use it.

同样的道理也适用于反过来,如果你提交一个需要X、Y和Z的函数,但你只提供了X和Y,那么你就会传入nil代替Z。
请参考这里的答案,因为你确实可以使用以下方法在表格中表示nil。
--  string  int   nil
t = {"var", "1", "nil"};

这个也值得一看: https://www.lua.org/pil/5.2.html - James Whyte
关于第二个例子,“值为nil的元素不被视为表的一部分。”请尝试运行代码 for k, v in pairs({1, nil, 3, 4}) do print(k, v) end - Tom Blodget
函数不像某些语言那样需要“声明”。这需要一些不同的思考方式。Vector是一个变量,在您的代码中,它在执行第一行非注释代码后引用一个函数值。函数调用在括号之前有一个表达式,该表达式会被计算,如果在运行时它产生了一个函数值,则传递所有参数进行调用。在调用站点上,无论调用的任何函数值期望多少个参数,都没有内在概念。 - Tom Blodget

4
长度运算符#仅适用于没有空洞的数组序列,即仅适用于符合直觉概念的长度。有关详细信息,请参见手册

而且它从索引 1 开始!如果你是 C/C++ 程序员,并且从该 API 的这一侧开始构建表格时,你天真地将 C 数组索引从 0 开始放入其中,那么事情就会变得混乱 - 我已经经历过了 - 并且获得了 T 恤衫... 8-P - SlySven

2
这取决于你对“有效”的定义。指向nil的键等同于该键不在表中,因此表中未分配给所有键的无限数量的键都指向nil。如果你希望你的数据结构以这种方式工作,当然可以将nil视为有效值。
正如lhf在他的答案中所说,如果nil出现在数组中的最后一个非nil元素之前,则#运算符不能一致地工作。如果你打算将你的表作为序列处理(与lhf发布的相同的链接),那么nil不是有效的数组元素。

2
# 的工作是一致的;只是它并不总是符合你的期望 :-) - lhf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接