Lua中如何使用#来覆盖字符串?

3

我正在尝试在Lua中实现自己的字符串长度方法。我已经成功地覆盖了字符串的len()方法,但是我不知道如何为#运算符做到这一点。

orig_len = string.len
function my_len(s)
  print(s)
  return orig_len(s)
end

string.len = my_len
abc = 'abc'

如果我调用:
print(abc:len())

它输出:
abc
3

但是。
print(#abc)

输出结果为“3”,这意味着它调用了原始的长度函数而非我的函数。有没有办法让#调用我的长度函数?

2个回答

7

在Lua中,即使使用元表,也无法覆盖字符串的#运算符:字符串不适用于__len元方法。

实际上,在Lua中没有任何操作符可以被“覆盖”。 Lua中的元方法是“回调函数”:当Lua无法自行执行时,它们会被使用。因此,算术元方法不适用于数字,长度元方法不适用于字符串。

对于表而言,情况有所不同,因为它们旨在实现Lua中的对象。


那么,没有办法做我需要的事情吗? - Xanx
1
@Xanx,不需要,除非你想用表格包装字符串。 - lhf

4

我正在尝试在Lua中实现自己的字符串长度方法。

你无法从Lua中完成这个任务。

你需要修改Lua源代码,特别是虚拟机(lvm.c),并更改它对操作码OP_LEN的处理。在Lua 5.2中,你需要更改luaV_objlen以在获取字符串的实际长度之前检查元方法:

case LUA_TSTRING: {
  tm = luaT_gettmbyobj(L, rb, TM_LEN);        // <--- add this line
  if (!ttisnil(tm))                           // <--- add this line
      break;                                  // <--- add this line
  setnvalue(ra, cast_num(tsvalue(rb)->len));
  return;
}

但这似乎是滥用运算符重载,就像将 + 重载为除法或其他操作一样。

滥用是正确的。Lua字符串是字节串而不是字符串。当然,有些函数可以根据区域设置将它们解释为字符,但字符串的长度永远不应被视为除了字节数之外的任何东西。 - Tom Blodget
我需要使Lua像本地一样处理utf-8字符串。我可以自己编写相关的函数,例如strlenstrsub,但是我希望utf-8处理对程序员来说是透明的,因此我需要Lua字符串函数能够与utf-8一起使用。 - Xanx
我相信这是Lua 5.3的一个特性。 - Mud

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