检查lua函数是否为匿名函数?
我在游戏中将回调注册为事件处理程序,如下所示:检查lua函数是否为匿名函数?,lua,Lua,我在游戏中将回调注册为事件处理程序,如下所示: --register event handler EventDispatcher:register("fire", mt.onPlayerFire, self) --this is the event handler mt:onPlayerFire() print("play fire") end --unregister event handler EventDispachter:unregister("fire", mt.onPl
--register event handler
EventDispatcher:register("fire", mt.onPlayerFire, self)
--this is the event handler
mt:onPlayerFire()
print("play fire")
end
--unregister event handler
EventDispachter:unregister("fire", mt.onPlayerFire, self)
当事件处理程序是模块mt
中的一个函数时,可以注销它,因为我可以在mt
中找到相同的函数来注销它,但是当我使用此表单时:
EventDispatcher:register("fire", function() doSomething() end, nil)
我无法注销事件处理程序,因为它是匿名的,所以我想在我的register
函数中添加一些检查,以防止匿名函数作为事件处理程序
我发现lua源代码中的Proto-struct可能会有所帮助,但我不知道每一部分的含义
我无法注销事件处理程序,因为它是匿名的
Lua中的每个函数都是匿名值。因此,您不能取消注册,不是因为它是匿名的,而是因为您没有保存对它的任何引用
如果传递的值(属于函数
类型)也保存在其他位置,则无法检测EventDispatcher:register()的内部。因此,如果您确实对同一事件有多个回调,并且您想要注销一个特定回调,那么您必须有一种方法来识别确切的回调函数
这意味着您应该将函数值保存在某个位置,以便它自己的值以后可以像现在一样用作unregister()
的标识符,或者返回添加回调时在register()
中生成的新回调实例id。无论哪种方式,都需要在EventDispatcher
之外存储一些东西来识别准确的回调
我无法注销事件处理程序,因为它是匿名的
Lua中的每个函数都是匿名值。因此,您不能取消注册,不是因为它是匿名的,而是因为您没有保存对它的任何引用
如果传递的值(属于函数
类型)也保存在其他位置,则无法检测EventDispatcher:register()的内部。因此,如果您确实对同一事件有多个回调,并且您想要注销一个特定回调,那么您必须有一种方法来识别确切的回调函数
这意味着您应该将函数值保存在某个位置,以便它自己的值以后可以像现在一样用作unregister()
的标识符,或者返回添加回调时在register()
中生成的新回调实例id。无论哪种方式,都有一些东西要存储在EventDispatcher
之外,以确定确切的回调。这种方法稍微避免了您的问题,但它可能会解决您的问题
注册新回调时,您可以简单地返回某种标识值,例如ID、表甚至函数本身。这可以让你在以后注销它
local firehandler = EventDispatcher:register("fire", function() do('something') end)
-- Do some stuff here...
EventDispatcher:unregister(firehandler)
缺点是,您可能必须更改事件调度器跟踪其已注册事件的方式,但在最坏的情况下,这意味着实现一些链表,在最好的情况下,您可以使用Lua表跟踪处理程序
至于检测匿名函数,这实际上是不可能的。Lua不区分就地定义的函数和存储在变量中的函数;这最终是同一件事
使用调试
库,通过将定义函数的文件/行与调用堆栈进行比较,这可能是可行的,但这只会在代码中引入错误,可能会非常缓慢。这种方法稍微避免了您的问题,但可能会解决您的问题
注册新回调时,您可以简单地返回某种标识值,例如ID、表甚至函数本身。这可以让你在以后注销它
local firehandler = EventDispatcher:register("fire", function() do('something') end)
-- Do some stuff here...
EventDispatcher:unregister(firehandler)
缺点是,您可能必须更改事件调度器跟踪其已注册事件的方式,但在最坏的情况下,这意味着实现一些链表,在最好的情况下,您可以使用Lua表跟踪处理程序
至于检测匿名函数,这实际上是不可能的。Lua不区分就地定义的函数和存储在变量中的函数;这最终是同一件事
通过使用debug
库,通过将定义函数的文件/行与调用堆栈进行比较,这可能是可行的,但这只是在代码中引入错误,可能会非常缓慢。您可以引入新函数unregister\u last()
能够在不指定的情况下注销上次注册的函数。注册系统将记住register()。注册系统将记住register()
调用的堆栈,并且unregister\u last()
函数将从此堆栈中“弹出”一个函数并将其注销。我使用数组跟踪特定事件的所有事件处理程序,并返回存储处理程序的数组索引,但问题是,当我注销前一个处理程序时,数组向下移动,使前一个返回的索引无效。所以我想我不应该使用数组来存储我的处理程序,还有什么建议吗?我使用数组来跟踪特定事件的所有事件处理程序,并返回存储处理程序的数组索引,但问题是当我取消注册前一个处理程序时,数组向下移动,使前一个返回的索引无效。所以我想我不应该使用数组来存储我的处理程序,还有什么建议吗?