Lua表长度函数重写不起作用

5

如何更改Lua中表的长度运算符(#)?手册建议在元表中分配__len函数,然后将该元表分配给要覆盖的表,但这并没有按预期工作。我无法在C端覆盖它。

turtles = {1,2,3}
setmetatable(turtles, {__len = function(mytable) return 5 end})

print(#turtles)
--returns 3, should return 5

可能是Lua字符串覆盖#的重复问题 - Larry Battle
@LarryBattle 这并不是重复的问题,这里的操作数不是字符串,而是一个表格。 - Yu Hao
你的代码在Lua在线演示中可以正常工作。 - lhf
1个回答

6
你必须使用Lua 5.1。自Lua 5.2以来,表上的__len元方法得到了支持。
Lua 5.1参考手册中,如果操作数是一个表,则直接返回原始表长度。

"len": the # operation.

function len_event (op)
   if type(op) == "string" then
     return strlen(op)         -- primitive string length
   elseif type(op) == "table" then
     return #op                -- primitive table length
   else
     local h = metatable(op).__len
     if h then
       -- call the handler with the operand
       return (h(op))
     else  -- no handler available: default behavior
       error(···)
     end
   end
 end
Lua 5.2参考手册中,如果操作数是一个表,则检查是否可用__len元方法。

"len": the # operation.

function len_event (op)
   if type(op) == "string" then
     return strlen(op)      -- primitive string length
   else
     local h = metatable(op).__len
     if h then
       return (h(op))       -- call handler with the operand
     elseif type(op) == "table" then
       return #op              -- primitive table length
     else  -- no handler available: error
       error(···)
     end
   end
 end

在您展示的Lua 5.1参考代码中,它清楚地提取元表并查找元方法 "__len",然后在原始表 "op" 上调用该元方法 "h"。然而,不合理的是,该代码永远不会被执行,因为 "elseif type(op)==“ table”" 将始终评估为 "true"(因为只有表可以具有元表)。下面的 else 中的代码永远不可能被执行。换句话说:虽然此功能的代码存在,但函数似乎编写不当。 - Hatefiend
在Lua中,表不是唯一具有元表的值。所有值都可以有关联的元表。特别地,在上面引用的Lua 5.1参考文献中的else子句经常用于实现userdata的#运算符。 - negamartin

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