3

Lisp in Small Pieces一书中,有以下示例代码,旨在演示call/cc可以模拟 goto。

(define (fact n)
   (let ((r 1) (k 'void))
      (call/cc (lambda (c) (set! k c) 'void))
      (set! r (* r n))
      (set! n (- n 1))
      (if (= n 1) r (k 'recurse))))

但是,我不确定我是否误解了某些东西,但我看不出这是call/cc模拟 goto 的方式。当k在最后一行应用时,恢复的延续具有原始延续的rn,其值不会被两个应用程序更改set!。所以整个循环永远不会终止。

这个例子中的书错了吗?还是我错过了什么?

4

1 回答 1

1

恢复的延续具有原始延续的 r 和 n,其值不会被这两个集合改变!应用程序。

没有; 这是重要的部分;值的更改可见的。它们没有被重置。我不确定这个问题是否应该被认为是重复的,但这也出现在 call-with-current-continuation - 状态保存概念中,提问者指出(查看整个上下文的问题) :

调用 next 3 次会产生 0、1 和 'done。这意味着当 state 使用生成器给出的函数 k 时,它并没有恢复程序的状态。

您可以通过在保存延续后打印 r 和 n 的值来非常简单地对此进行测试。您会看到更新的值在那里。例如:

(define (fact n)
  (let ((r 1) (k 'void))
    (call-with-current-continuation (lambda (c) (set! k c) 'void))
    (display "r: ") (display r) (newline)
    (display "n: ") (display n) (newline)
    (set! r (* r n))
    (set! n (- n 1))
    (if (= n 1) r (k 'recurse))))

> (fact 6)
r: 1
n: 6
r: 6
n: 5
r: 30
n: 4
r: 120
n: 3
r: 360
n: 2
720

相关问题:

另见:

于 2015-02-12T22:11:52.547 回答