方案 - 为什么内存终止?

时间:2013-02-04 12:07:45

标签: loops scheme

有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内存终止? 如果我在正确的情况下,在一个循环中进行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相同!

1 个答案:

答案 0 :(得分:0)

在智能编译器中,案例1和案例2是等效的。即使没有智能编译器,每次重新创建lambdas,情况2也可能创建无限数量的lambdas,但它们可以立即进行垃圾收集。所以结果是一样的:持续堆栈和堆使用。

在第3种情况下,每个新lambda都包含对前一个lambda的自由引用,因此创建的lambda中没有一个是可垃圾收集的。你仍然有不断的堆栈使用,但堆使用量会膨胀。 (一个非常聪明的编译器可以发现lambda实际上是未使用过的,并且完全消除了这一点,但是关于自由引用的一般观点仍然存在。)

编译器还可以直接用(lambda () (b))替换b,如果它可以证明b已经是一个nullary(-only)过程,并且/或者它可以证明结果lambda只会以一种无效方式调用(否则,它必须添加类型和arity检查器)。同样,为了适用于您的示例,需要一个非常智能的编译器。