【发布时间】:2011-12-20 17:32:09
【问题描述】:
我有这个修改过的代码示例,我取自关于匿名函数的维基百科文章。
comp(threshold)
{
return lambda(x)
{
return x < threshold;
};
}
main()
{
a = comp(10);
lib::print( a(5) );
}
匿名函数应该不会太难添加到我的脚本语言中。它应该只是以正常方式添加函数代码的情况,除了访问该函数的唯一方法是通过分配它的变量。
上述闭包示例的问题在于,匿名函数的函数体引用(在一般意义上)在调用闭包时无效(或将是)的内存位置。
我已经想到了两个可能的解决方案;在我尝试将此功能添加到我的语言之前,我只想先获得一些建议。
【问题讨论】:
-
这与游戏开发无关,应该移至 stackoverflow。
-
你必须以某种方式捕捉上下文。 C++ 有两个选项 - 您可以通过引用(在这种情况下,lambda 秘密地在实例中保留一个指针/引用,并且不能有效地超出范围)或按值(在这种情况下,lambda 对象需要秘密地保留一个在实例中复制)。不过,您的语言可能允许第三个选项——无论您用作堆栈,如果 lambda 对象可以保留对堆栈帧的引用,并且如果堆栈帧本身是垃圾收集的(或类似的),那么 lambda 的存在可以延长该局部变量的存在。
-
另一种选择是通过 CPS 变换执行闭包消除。这就是 Scheme 实现的作用(不难理解,请阅读 Scheme 的创建者 Guy Lewis Steele 的 Lambda the Ultimate XXX 论文)。您将需要为此进行垃圾收集,因为它相当于(一个理智的版本)@SteveJessop 的第三个选项。
-
有很多方法可以做到这一点。你能更详细地描述你的脚本语言吗?例如,它是否支持动态调度?您希望封闭的局部变量具有词法范围(如在 C# 中)还是动态范围(如在 PostScript 中)?功能已经“一流”了吗?您的语言执行多少静态类型分析?您能否表示类/记录/结构/关联数组/等之类的东西,如果可以,如何表示?
-
见Implementation of closures in Lua,Nicol Bolas 的回答非常好
标签: c++ scripting lambda closures scripting-language