在Lua中更改metatable会破坏冒号运算符

时间:2013-08-11 03:43:09

标签: lua lua-table metatable

在学习Lua时,我从here借了一些代码 使用字符串索引,正是这样:

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)

调试print()告诉我__index函数正在str:len()上调用,而i参数正在成为字符串“len”。我知道str:len()在没有metatable的情况下工作,但是一旦我添加它就会发生这种情况,为什么?

2 个答案:

答案 0 :(得分:3)

来自Lua 5.2 Refernce Manual:String Manipulation

  

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

因此,像str:len()这样的面向对象样式来自您修改过的默认元方法__index

答案 1 :(得分:2)

索引函数传递给表,以及正在索引的键。所以'str'应该是字符串,'i'应该是你的情况下的关键。因为“len”不在元表中,所以它调用__index并将字符串作为第一个参数传递,将键(“len”)作为第二个参数传递。它看起来好像你需要检查'i'的类型,看看如何更好地处理字符串

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])

请参阅here了解详情