0

有 3 个程序我试图了解堆栈和堆中发生了什么。都是无限循环

1.

  (let ((f (lambda () 'ok))
        (g (lambda (a b) (a a b))))
           (g g f))

所有应用程序都是尾递归 - 堆栈是好的。只创建了 2 个 lambda - 所以堆没问题。我对吗?

2.

   (let ((f (lambda (a b)
               (a a (lambda () 'ok)))))
     (f f (lambda () 'ok)))

所有的应用程序都是尾递归 - 堆栈是好的。关于堆:创建了无限的 lambda (lambda () 'ok))。我对吗?- 那么为什么内存没有被终止呢?

最后一个:

3.

   (let ((f (lambda (a b)
                (a a (lambda () (b))))))
       (f f (lambda () 'ok)))

2和3有什么区别?为什么在 2 内存终止?如果我underdatnd正确,在3后一个循环:

 we activate this: (lambda (a b)  (a a (lambda () (b)))
 on                (lambda (a b)  (a a (lambda () (b)))
 and this          (lambda () 'ok)  (becuse this is (b)..)

这和2一样!

4

1 回答 1

0

在智能编译器中,案例 1 和案例 2 是等价的。即使没有智能编译器,因此每次都会重新创建 lambda,案例 2 可能会创建无限数量的 lambda,但它们会立即被垃圾回收。所以结果是一样的:常量栈和堆使用。

在案例 3 中,每个新的 lambda 都包含对前一个 lambda 的自由引用,因此所创建的 lambda 都不是可垃圾回收的。您仍然有恒定的堆栈使用量,但堆使用量会激增。(一个非常聪明的编译器可以找出 lambda 实际上是未使用的,并完全消除它,但我关于自由引用的一般观点是成立的。)

如果编译器可以证明它已经是一个 nullary( (lambda () (b))-only ) 过程,和/或如果它可以证明生成的 lambda 只会以 nullary 方式调用(否则,它必须添加类型和arity 检查器)。同样,为了将其应用于您的示例,它需要一个非常智能的编译器。bb

于 2013-02-04T13:16:40.470 回答