如何管理自引用跨谱lambda? [英] How does one manage a self-referring cross-scope lambda?
问题描述
假设我有一个想在计时器结束时调用的功能.我已将该功能放在lambda函数中.此外,在该函数中,我可能希望设置另一个计时器,以便在以后的另一个场合调用相同的lambda.
Assume that I have a functionality which I want to call whenever a timer finishes. I have put that piece of functionality in a lambda function. Furthermore, in that function, I may wish to set another timer to call that same lambda on another, later occasion.
void doSetupThingsInSomeDecoupledCodeOrWhatever() {
std::function<void(float)> semiRecursiveFunc;
semiRecursiveFunc = [&semiRecursiveFunc](float deltaT){
if (whatever()) {
// Do something...
}
else {
// Do something else, then:
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
// Gives the timer a duration to wait, and a function to run at the end of it.
getTimerSystem().setNewTimer(durationMS, semiRecursiveFunc);
}
};
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
// Gives the timer a duration to wait, and a function to run at the end of it.
getTimerSystem().setNewTimer(durationMS, fooLambda);
}
现在,显然这是行不通的,因为 semiRecursiveFunc
已绑定到 doSetupThingsInSomeDecoupledCodeOrWhatever
的范围,并且当计时器系统尝试运行该功能时,该功能将不再有效存在,一切都会分解成一个壮观的火焰球.
Now, clearly this won't work, because semiRecursiveFunc
is tied to the scope of doSetupThingsInSomeDecoupledCodeOrWhatever
, and when the timer system tries to run it the function will no longer exist and everything will disintegrate into a spectacular ball of flame.
管理此问题的最佳方法是什么?我无法将 semiRecursiveFunc
存储在指针中,因为据我所知,不能这样声明lambda.对于这种持久性lambda用例,是否有一些通用工具?什么是最丑陋的方法,而周围的基础结构却最少?是否有最佳实践可循,我错过了一些相关工具?任何建议都将不胜感激.
What's the best way to manage this? I can't store semiRecursiveFunc
in a pointer because one can't declare lambdas like that, as far as I can tell. Is there some common tool for this sort of persistent-lambda use-case? What's the least ugly approach, with minimum surrounding infrastructure? Is there a best-practice to follow, some relevant tool I've missed? Any suggestions or recommendations would be much appreciated.
推荐答案
您正在寻找的是一个y-combinator ,有时称为
What you're looking for is a y-combinator, sometimes called a fixed-point combinator.
无论哪种方式,您都不必像这样完全使用 std :: function
(这会增加不必要的开销),而是这样编写回调:
Either way, instead of using std::function
at all (which adds needless overhead), you would write your callback like this:
auto semiRecursiveCallback = combinator([](auto self, float deltaT){
if (whatever()) {
// Do something...
}
else {
// Do something else, then:
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
// Gives the timer a duration to wait, and a function to run at the end of it.
// NB: we pass 'self' as the argument
getTimerSystem().setNewTimer(durationMS, self);
}
});
其中 combinator
是我的链接答案的 y_combinator
实现,或者来自优秀的Boost.HOF库的 boost :: hof :: fix
Where combinator
is either the y_combinator
implementation of my linked answer or boost::hof::fix
from the excellent Boost.HOF library.
组合器确保对象本身可以访问自身,因此您可以执行递归操作.在上面的代码中,您实际上是在传递自己的副本,但这很好:值语义很酷.
The combinator ensures that the object itself has access to itself, so you can do recursive things. In the above code, you're actually getting passed a copy of yourself, but that's fine: value semantics are cool like that.
这篇关于如何管理自引用跨谱lambda?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!