Compiler construction 理解编译器中递归闭包的建模

Compiler construction 理解编译器中递归闭包的建模,compiler-construction,closures,lisp,Compiler Construction,Closures,Lisp,我介绍了两种为类似lisp语言的递归闭包建模的方法。假设我有以下代码: (letrec ((f (fun (l) … (map f l) …)))) …) 
 对于f对应的闭包,我可以: 将f视为一个自由变量,并将其置于自己的环境中,从而导致循环闭包 对于平面闭包,环境就是闭包,可以直接重用 我使用的是平面闭包的概念,它在第一个单元格中存储一个指向函数的指针,在其余单元格中存储自由变量。但我对第二个选项感到困惑,因为在我看来,第一个和第二个调用接收不同的参数。那么,它们如何可能得到相同的闭包

我介绍了两种为类似lisp语言的递归闭包建模的方法。假设我有以下代码:

(letrec ((f (fun (l) … (map f l) …)))) …)

 对于
f
对应的闭包,我可以:

  • f
    视为一个自由变量,并将其置于自己的环境中,从而导致循环闭包
  • 对于平面闭包,环境就是闭包,可以直接重用
  • 我使用的是平面闭包的概念,它在第一个单元格中存储一个指向函数的指针,在其余单元格中存储自由变量。但我对第二个选项感到困惑,因为在我看来,第一个和第二个调用接收不同的参数。那么,它们如何可能得到相同的闭包,而不需要将递归调用作为自由变量来区分它们呢


    也许您可以在典型编译器的后续步骤中解释如何解决这一问题?

    每次调用
    f
    都会创建一个新的闭包,其中包含
    l
    的新值(假设词法范围)。
    f
    主体中的闭包通常不包含
    f
    ,但父对象将包含闭包,因此您将在调用堆栈中进行查找

    我写了一篇关于这一点的帖子: