gpt4 book ai didi

callback - Lua - 如何将对象的函数作为参数传递给另一个函数

转载 作者:行者123 更新时间:2023-12-04 02:12:31 25 4
gpt4 key购买 nike

local a = {}
function a:test1(value)
print(value)
end
local b = {}
function b:test2(v1, v2)
v2(100);
end
b:test2(_, a.test1)

不工作。值为零。我可以找到在匿名函数中进行封装的解决方案
b:test2(variable, function(value) a:test1(value) end)

但我觉得这很糟糕 mkay

什么是正确的语法?

最佳答案

anotherObject:aFunction(variable, object.doStuff)是正确的语法。

使用冒号 : with a function 只是带有隐式 self 的调用或声明的语法糖参数作为第一个参数。如果您想以更简洁的方式遵循示例中显示的模式,可以使用辅助函数。

local function bind(t, k)
return function(...) return t[k](t, ...) end
end

然后你像这样应用它。
anotherObject:aFunction(variable, bind(object, 'doStuff'))

编辑:我相信您的问题的解决方案将需要在某种程度上进行绑定(bind),而无需修改 Lua 解释器或使用代码翻译步骤。
这基本上是因为 Lua 中的函数不携带任何有关其来源的信息。 IE。 ,表本身并不拥有它们存储的函数。

例如,以下是完全合法的 Lua 代码。
function Circle:area() -- function Circle.area(self)
-- ...
end

-- Evaluate the function in the "area" slot with Square as the self parameter.
Circle.area(Square)

当然,您可以尝试进行范式转换,但是如果您要构建一个完整的应用程序,其基础是函数与它们已被索引的表相关联,如您所说,这可能为时已晚。
因此,我提出以下 疯狂解决方案。
local mt = {}

function mt:__index(k)
local v = self._slots[k]

if v == nil then
-- Ascend the inheritance tree.

-- This has to be done with rawget all the way up,
-- otherwise inherited functions would be repeatedly bound.
local p = self

repeat
p = rawget(p, '_parent')
if not p then break end
v = p._slots[k]
until v
end

if type(v) == 'function' then
-- Return a self-bound version of the function.
return function(...) return v(self, ...) end
end

return v
end

function mt:__newindex(k, v)
self._slots[k] = v
end

--- Demo & Tests ---

local function Object(parent)
local o = setmetatable({_slots = {}}, mt)
if parent then rawset(o, '_parent', parent) end
return o
end

local o1 = Object()
local o2 = Object(o1)

assert(o1.abc == nil, 'o1.abc should be nil')
o1.abc = 3
assert(o1.abc == 3, 'o1.abc should be 3')
assert(o2.abc == 3, 'o2.abc should be 3, inherited from o1')
o2.abc = 7
assert(o2.abc == 7, 'o2.abc should be 7, overriding o1')
assert(o1.abc == 3, 'o1.abc should be 3, unaffected by o2 setter')

function o1:test(bar)
return self.abc + bar
end

assert(type(o1.test) == 'function', 'o1.test should be a function')
assert(type(o2.test) == 'function', 'o2.test should be a function, inherited from o1')

assert(o1.test(5) == 8, 'o1.test(5) should return 3 + 5 = 8')
assert(o2.test(11) == 18, 'o2.test(11) should return 7 + 11 = 18')

function o2:test2(fn)
return self.abc + fn(7)
end

assert(o2.test2(o1.test) == 17, 'o2.test2(o1.test) should return 7 + (3 + 7) = 17')

o2.test3 = o1._slots.test -- proper function copying
assert(o2.test3(11) == 18, 'o2.test3(5) should return 7 + 11 = 18')

o2.abc = nil
assert(o2.abc == 3, 'o2.abc should be 3 again, inherited from o1 after clearing')

o2.abc = false
assert(o2.abc == false, 'o2.abc should be false, __index needs to differentiate between nil and false')

该元表将为您提供所需的内容,以及要启动的继承和绑定(bind)功能。您只需确保要遵循此模式的所有表也遵循示例代码中显示的对象创建方法。

解释一下,以这种方式创建的每个表都有任何新分配重定向到 _slots子表和任何新的检索检查了 _parent继承树。如果值的类型是 function ,然后它返回一个带有原始 self 的新闭包开始检查绑定(bind)到找到的函数。

显然,使用 : 从这些对象之一调用函数冒号语法将是一个愚蠢的想法,因为它的计算结果为 o.fn(o, o) ,这可能不是你想要的。另一个需要注意的是,从这些对象复制函数到这些对象上不会按预期工作。 o1.newfn = o2.fn将放一个 o2将函数绑定(bind)到 o1 , 反过来又会重新绑定(bind)到 o1 .最终结果将类似于 o2.fn(o2, o1) .您必须从 _slots 复制函数 table 。

总之:尽管这可行,但从长远来看,我个人不会推荐它,因为它可能会让习惯于 Lua 如何处理表、索引和函数的任何人感到困惑,并且会产生开销。您也许可以通过 memoizing 取消一些它。关闭,但我会把这个决定留给你。祝你好运!

关于callback - Lua - 如何将对象的函数作为参数传递给另一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20022379/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com