Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检查lua函数是否为匿名函数?_Lua - Fatal编程技术网

检查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()
函数将从此堆栈中“弹出”一个函数并将其注销。我使用数组跟踪特定事件的所有事件处理程序,并返回存储处理程序的数组索引,但问题是,当我注销前一个处理程序时,数组向下移动,使前一个返回的索引无效。所以我想我不应该使用数组来存储我的处理程序,还有什么建议吗?我使用数组来跟踪特定事件的所有事件处理程序,并返回存储处理程序的数组索引,但问题是当我取消注册前一个处理程序时,数组向下移动,使前一个返回的索引无效。所以我想我不应该使用数组来存储我的处理程序,还有什么建议吗?