在Lua中更改元表会破坏冒号操作符。

学习 Lua 时,我从这里借用了一些代码来使用字符串索引,它就是这样的:

getmetatable("").__index = function(str, i) return string.sub(str, i, i) end

之后,我写了一个函数来练习翻转字符串。

function reverse_string(str)
    local s = ""
    for i = string.len(str), 1, -1 do s = s .. str[i] end
    return s
end

这个函数很好用,直到我把string.len(str)改成 str:len(),然后我就收到了这个错误:

reverse.lua:9: bad argument #2 to 'sub' (number expected, got string)

调试输出告诉我__index函数正在str:len()上被调用,而且i参数变成了字符串“len”。我知道str:len()在没有metatable的情况下是有效的,但是一旦我加入metatable就会出现这种情况,为什么?

点赞
用户1009479
用户1009479

Lua 5.2参考手册:字符串操作中翻译如下:

字符串库提供了所有函数,放置在字符串表中。它还为字符串设置了一个元表,其中__index字段指向字符串表。因此,您可以使用面向对象的风格来使用字符串函数。例如,字符串.byte(s, i)可以写为s:byte(i)。

因此,像str:len()这样的面向对象风格来自于默认的元方法__index,您可以对其进行修改。

2013-08-11 04:07:43
用户2406646
用户2406646
getmetatable("").__index = function(str, key)
  if type(key) == "string" then
    return string[key]
  else
    return string.sub(str, key, key)
  end
end

str = "hello, world!"
print(str:len())
print(str[5])

index 函数会接收到表和键值作为参数,因此在本例中, str 代表字符串,i 则代表键值。因为 len 不在元表中,所以调用了 __index 并以字符串作为第一个参数,以键值 ("len") 作为第二个参数。需要检查 i 的类型以更好地处理字符串。请参考 这里 获取更多信息。

2013-08-11 04:08:56