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

see*_*con 1 lua lua-table

我正在尝试像 Python 一样向字符串添加索引。这有效:

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

str1 = 'hello'    
print(str1[1])
Run Code Online (Sandbox Code Playgroud)

这不会:

getmetatable('').__index = function(str, i) return str:sub(i, i) end
Run Code Online (Sandbox Code Playgroud)

给出以下错误:

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 ?
Run Code Online (Sandbox Code Playgroud)

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

nob*_*ody 5

str:method快捷方式通过__index. 通过重新定义__index,你就打破了这一点。

\n\n

从5.2或5.3开始,Lua为字符串定义了一个元表,大致如下

\n\n
debug.setmetatable( "", { __index = string } )\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
\n\n

现在你过来说

\n\n
getmetatable(\'\').__index = function(str, i) return str:sub(i, i) end\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,如果您说("foo")[2],则调用__index( "foo", 2 ),并在其中导致查找("foo")["sub"](在 中str:sub(i, i))。这会调用__index( "foo", "sub" ),并在其中导致查找("foo")["sub"](在 中str:sub(i, i))。这调用__index( "foo", "sub" ), 和\xe2\x80\xa6

\n\n

\xe2\x80\xa6 并且堆栈溢出,因为你会("foo")["sub"]永远查找。

\n\n
\n\n

以您所做的方式重新定义__index意味着您不能再使用该快捷方式,这意味着您必须拼写出您使用的库代码,string.method而不是在代码中的str:method 所有位置, \xe2\x80\xa6 \xe2\x80 \x93 或者你保持它兼容。

\n\n

字符索引仅对数字有意义,因此您可以通过说来获得两者

\n\n
getmetatable( "" ).__index = function( str, k )\n    if type( k ) ~= "number" then  return string[k]  end -- lookup in string.*\n    return str:sub( k, k )\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

这仅需要string.sub数字索引。方法名称是字符串,因此仍然会在string.

\n