语法糖在Lua中的metatable声明中不起作用

时间:2017-08-31 11:46:11

标签: lua lua-table

我正在尝试为Python中的字符串添加索引。这有效:

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

str1 = 'hello'    
print(str1[1])

这不是:

getmetatable('').__index = function(str, i) return str:sub(i, i) end

发出以下错误:

lua: test.lua:1: C stack overflow
stack traceback:
    test.lua:1: in function '__index'
    test.lua:1: in function '__index'
    ...
    test.lua:1: in function '__index'
    test.lua:4: in main chunk
    [C]: in ?

是否有某种循环发生?为什么呢?

1 个答案:

答案 0 :(得分:4)

str:method快捷方式可通过__index运行。通过重新定义__index,你可以打破它。

自5.2或5.3以来,Lua为字符串定义了一个metatable,大致类似于

debug.setmetatable( "", { __index = string } )

允许撰写("foo"):sub( i, j )

现在你过来说

getmetatable('').__index = function(str, i) return str:sub(i, i) end

所以,如果您说("foo")[2],那就会调用__index( "foo", 2 ),而这会导致查找("foo")["sub"](在str:sub(i, i)中)。这会调用__index( "foo", "sub" ),并在其中导致查找("foo")["sub"](在str:sub(i, i)中)。这会调用__index( "foo", "sub" )和...

...并且堆栈溢出,因为您永远查找("foo")["sub"]

以您的方式重新定义__index意味着您无法再使用该快捷方式,这意味着您必须拼出string.method而不是str:method 代码中的无处不在,您使用的库代码,...... - 或者您保持兼容。

字符索引仅对数字有意义,因此您可以通过说

来获得两者
getmetatable( "" ).__index = function( str, k )
    if type( k ) ~= "number" then  return string[k]  end -- lookup in string.*
    return str:sub( k, k )
end

这只会为string.sub调用数字索引。方法名称是字符串,因此仍然会在string中查找它们。