使用table.pack为表添加“n”字段的目的是什么?真的需要table.pack吗?

标题说的很明白。我想知道为什么Lua使用table.pack()时会向表中添加一个“n”字段。

实现方法如下:

function pack(...)
    return { n = select("#", ...), ... }
end

-- 感觉没啥用

我不认为有什么意义,因为你可以使用{}来构造一个表,并使用#tbl来获取表中元素的数量。

local tbl = table.pack('a', 'b', 'c', 'd')
print(tbl.n, #{ 'a', 'b', 'c', 'd' }) -- 4    4

-- 同样的结果

如果你使用next遍历通过table.pack构造的表,会破坏遍历的次序。当然,你可以使用ipairs,但对于那些不熟悉的人来说呢?并且长度运算符不会计算n

点赞
用户3204551
用户3204551

table.pack() 不一定返回一个序列。它只有当所有的参数都不是 nil 时才返回一个序列。

因此,在通用情况下,如果要翻转它,你需要使用 "n" 成员。

table.unpack(t, 1, t.n)

尽管实现非常简单,table.pack() 仍然是一个有用的抽象。

2019-11-20 20:06:44
用户4984564
用户4984564
local tbl = table.pack('a', 'b', nil, 'd', nil)
print(tbl.n, #{ 'a', 'b', 'c', 'd' }) -- 5    2

-- 非常不同的事情

就是这样。它很容易实现,但这并不意味着您应该为每个项目手动实现它。

如果您使用 next 遍历使用 table.pack 构造的表格,它会破坏迭代。

是的,那就是为什么您 使用 next 迭代序列。而是使用 ipairs,它是为此而设计的。

  1. next 比 ipairs 慢(PUC 和 JIT 都是如此)
  2. next 不按顺序迭代
  3. 使用 ipairs 是 Lua 的约定

哦,并且长度运算符不会计算那个 n。

默认情况下不会,但您可以编写一个元方法来解决这个问题,这真的不是什么大问题。

local meta = { __len = function(self) return self.n or rawlen(self) end }
print(#setmetatable(table.pack('a', 'b', nil, 'd', nil))) -- 5
2019-11-21 07:42:11