Lua 内部:字符串方法如何作为方法工作?
Lua internals: how do string methods work as methods?
Lua 有一块允许实现 OOP 方法的语法糖:运算符 :
当用作 foo:bar(biz)
时等同于 foo.bar(foo,biz)
。但是,我注意到标准字符串库也以这种方式积极使用它:
local a = "a normal string"
local b = a:reverse() -- ????????
print(b)
-- outputs: gnirts lamron a
问题是:这究竟是如何实现的?自然地,当您尝试假设它扩展为 a.reverse(a)
时它会分崩离析,因为 a
是一个字符串并且不可能包含键 reverse
,此外,该语句实际上等同于 string.reverse(a)
。我的直觉是它实际上扩展到 _G[type(a)].reverse(a)
,但你记得同样的事情发生在文件描述符的 io
库中......
Lua (5.1 - 5.4) 中的每个字符串都有一个带有元方法的元表 __index。
那是所有字符串函数都存在的地方。
这是一个显示它的函数...
-- help()
help=function(help)
dump(debug.getmetatable(help).__index)
end
这很简单,不是吗?
编辑:因为我忘记了转储功能:-) ...
-- dump(table)
dump=function(...)
local args={...}
local test,dump=pcall(assert,args[1])
if test then
for key,value in pairs(dump) do
io.write(string.format("%s=%s\n",key,value))
io.flush()
end
return true
else
return test,dump
end
end
有一个名为 _VERSION 的字符串 - 让我们看一下...
>help(_VERSION)
reverse = function: 0x565c4870
lower = function: 0x565c4ab0
sub = function: 0x565c7020
byte = function: 0x565c6d30
gsub = function: 0x565c7bb0
char = function: 0x565c4d80
format = function: 0x565c5060
unpack = function: 0x565c62d0
gmatch = function: 0x565c6ee0
dump = function: 0x565c5a90
upper = function: 0x565c47e0
find = function: 0x565c7ba0
len = function: 0x565c44d0
rep = function: 0x565c4900
pack = function: 0x565c66e0
packsize = function: 0x565c61c0
match = function: 0x565c7b90
这就是它作为方法与 .
和 :
一起工作的原因
冒号语法真的等同于点语法加上 self 参数。所以问题是,a.reverse
是如何工作的?
The string library provides all its functions inside the table string
. It also sets a metatable for strings where the __index
field points to the string
table. Therefore, you can use the string functions in object-oriented style. For instance, string.byte(s,i)
can be written as s:byte(i)
.
我们可以通过代码查看这些元表的详细信息:
local a = "a normal string"
strindex = getmetatable(a).__index
if type(strindex) == "table" then
print "string has metatable entry __index:"
for k,v in pairs(strindex) do
local same = (v == string[k])
print(k, type(v), "same as string."..k..":", same)
end
end
local b = a.reverse(a) -- ????????
print(b)
-- outputs: gnirts lamron a
Try it online!:输出为
string has metatable entry __index:
rep function same as string.rep: true
byte function same as string.byte: true
sub function same as string.sub: true
char function same as string.char: true
gmatch function same as string.gmatch: true
format function same as string.format: true
reverse function same as string.reverse: true
match function same as string.match: true
dump function same as string.dump: true
len function same as string.len: true
packsize function same as string.packsize: true
find function same as string.find: true
unpack function same as string.unpack: true
upper function same as string.upper: true
pack function same as string.pack: true
lower function same as string.lower: true
gsub function same as string.gsub: true
gnirts lamron a
Lua 有一块允许实现 OOP 方法的语法糖:运算符 :
当用作 foo:bar(biz)
时等同于 foo.bar(foo,biz)
。但是,我注意到标准字符串库也以这种方式积极使用它:
local a = "a normal string"
local b = a:reverse() -- ????????
print(b)
-- outputs: gnirts lamron a
问题是:这究竟是如何实现的?自然地,当您尝试假设它扩展为 a.reverse(a)
时它会分崩离析,因为 a
是一个字符串并且不可能包含键 reverse
,此外,该语句实际上等同于 string.reverse(a)
。我的直觉是它实际上扩展到 _G[type(a)].reverse(a)
,但你记得同样的事情发生在文件描述符的 io
库中......
Lua (5.1 - 5.4) 中的每个字符串都有一个带有元方法的元表 __index。
那是所有字符串函数都存在的地方。
这是一个显示它的函数...
-- help()
help=function(help)
dump(debug.getmetatable(help).__index)
end
这很简单,不是吗?
编辑:因为我忘记了转储功能:-) ...
-- dump(table)
dump=function(...)
local args={...}
local test,dump=pcall(assert,args[1])
if test then
for key,value in pairs(dump) do
io.write(string.format("%s=%s\n",key,value))
io.flush()
end
return true
else
return test,dump
end
end
有一个名为 _VERSION 的字符串 - 让我们看一下...
>help(_VERSION)
reverse = function: 0x565c4870
lower = function: 0x565c4ab0
sub = function: 0x565c7020
byte = function: 0x565c6d30
gsub = function: 0x565c7bb0
char = function: 0x565c4d80
format = function: 0x565c5060
unpack = function: 0x565c62d0
gmatch = function: 0x565c6ee0
dump = function: 0x565c5a90
upper = function: 0x565c47e0
find = function: 0x565c7ba0
len = function: 0x565c44d0
rep = function: 0x565c4900
pack = function: 0x565c66e0
packsize = function: 0x565c61c0
match = function: 0x565c7b90
这就是它作为方法与 .
和 :
冒号语法真的等同于点语法加上 self 参数。所以问题是,a.reverse
是如何工作的?
The string library provides all its functions inside the table
string
. It also sets a metatable for strings where the__index
field points to thestring
table. Therefore, you can use the string functions in object-oriented style. For instance,string.byte(s,i)
can be written ass:byte(i)
.
我们可以通过代码查看这些元表的详细信息:
local a = "a normal string"
strindex = getmetatable(a).__index
if type(strindex) == "table" then
print "string has metatable entry __index:"
for k,v in pairs(strindex) do
local same = (v == string[k])
print(k, type(v), "same as string."..k..":", same)
end
end
local b = a.reverse(a) -- ????????
print(b)
-- outputs: gnirts lamron a
Try it online!:输出为
string has metatable entry __index:
rep function same as string.rep: true
byte function same as string.byte: true
sub function same as string.sub: true
char function same as string.char: true
gmatch function same as string.gmatch: true
format function same as string.format: true
reverse function same as string.reverse: true
match function same as string.match: true
dump function same as string.dump: true
len function same as string.len: true
packsize function same as string.packsize: true
find function same as string.find: true
unpack function same as string.unpack: true
upper function same as string.upper: true
pack function same as string.pack: true
lower function same as string.lower: true
gsub function same as string.gsub: true
gnirts lamron a