我得到了有关为类 lisp 语言建模递归闭包的两种方法的描述。假设我有以下代码:
(letrec ((f (fun (l) … (map f l) …)))) …)
对于对应于 f
的闭包,我可以:
- 将
f
视为一个自由变量,并将其置于自己的环境中,从而导致循环闭包。 - 使用平面闭包,环境就是闭包,可以直接重用。
我使用的是平面闭包的概念,它在第一个单元格中存储一个指向函数的指针,在其余单元格中存储自由变量。但是我对第二个选项感到困惑,因为在我看来,第一次和第二次调用接收不同的参数。那么它们怎么可能获得相同的闭包并且不需要将递归调用作为自由变量包括在内来区分它们呢?
也许您可以解释一下在典型编译器的后续步骤中如何解决这个问题?
最佳答案
每次调用 f
都会为 l
创建一个新的闭包(假设词法范围)。 f
主体中的闭包通常不包含 f
,但父级包含,因此您最终将查找调用堆栈。
我写了一篇更深入的帖子:http://cinigl.io/posts/nested-variable-scoping
关于compiler-construction - 了解编译器中递归闭包的建模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43232861/