将一个函数的参数传递给另一个函数时,使用元表

我正在学习Lua,并到了元表部分,在这个例子中


local tb = {}
local meta = {}

function tb.new(s)
local super = {}
super.s = s

setmetatable(super,meta)

return super
end

function tb.add(s1,s2)

return s1.s..s2.s

end

meta.__add = tb.add

f= tb.new("W")
t= tb.new("E")

print(f+t)

在这个部分

function tb.add(s1,s2)

return s1.s..s2.s

end

super.s 中的值如何传递到 tb.add 函数。我注意到 s1.ss2.s 中的变量 s 似乎是 tb.newtb.add 之间的链接。

而且,在这一部分中

f= tb.new("W")
t= tb.new("E")
print(f+t)

当编译器到达 f+t 时,我认为首先调用这个函数: f= tb.new("W") 在这个函数中现在没有 s2,所以它应该是空的, return s1.s..s2.s 怎么会发生的呢?

点赞
用户3574628
用户3574628

tb.new 基本上只是创建一个新表并返回它,所以在这段代码中:

f= tb.new("W")
t= tb.new("E")

……ft 是新创建的表,每个表都有一个 s 字段,且都具有相同的元表。

当解释器看到 f+t 时,它会自动调用 meta.__add 并将两个操作数作为参数传递。 tb.add 有两个参数,并假定它们都有一个 s 字段,这个字段是一个字符串,所以这一切都完美地进行检查。如果 t 不是一个具有 s 字段的表,那么你就会有麻烦了。

换句话说,tb.new 不会将 s 传递给 tb.addtb.news 存储在新表中,并且 tb.add 从其参数中检索该值。

2021-04-04 13:16:39
用户2858170
用户2858170

你的代码缺少一个名为tb的表格。否则,将出现错误,并导致从nil值进行索引。

你的代码创建两个表格值,一个具有 s =“E” 字段,另一个具有s =“W”字段。两个表格都共享相同的元表meta,该元表实现了__add元方法。

来自Lua 5.4参考手册2.4-元表和元方法

在Lua中,每个值都可以有一个元表。该元表是一个普通的Lua表,它定义了在某些事件下原始值的行为。通过在其元表中设置特定字段,您可以更改值的行为的多个方面。例如,当一个非数字值是加法的操作数时,Lua会在值的元表字段__add中查找函数。如果找到,则Lua调用此函数执行加法。

因此,对于f + t将调用meta._add(f, t),它返回f.s..t.s

2021-04-04 13:18:55
用户11740758
用户11740758

正如 @lhf 的评论和 @Piglet 的回答,代码并不像原来那样能够工作。

这里有一个经过修正的版本,使用/显示了新的 Lua 5.4 warn()

它可以用于调试,因为 @on@off 让你控制输出。

以下是代码...

if warn==nil then warn=print else warn('@on') end
local meta={}
local tb={}

function tb.new(s)
 warn('tb.new("'..s..'")')
 local super={}
 super.s=s
 setmetatable(super,meta)
 return super
end

function tb.add(s1,s2)
 warn('__add('..tostring(s1)..', '..tostring(s2)..')')
 return s1.s..s2.s
end

meta.__add=tb.add

f=tb.new("W")
t=tb.new("E")

print('Print: ',f+t)

输出结果是...

Lua warning: tb.new("W")
Lua warning: tb.new("E")
Lua warning: __add(table: 0x5661f510, table: 0x5661f580)
Print:  WE

(在早于 Lua 5.4 的版本中,会使用 print() 而不是 warn() 。)

2021-04-04 18:47:13