在 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
时,已恢复的续约内容包含原始续集的r
和n
,其值不由两个{更改} {1}}应用程序。所以整个循环永远不会终止。
这个例子中的书是错的吗?或者我错过了什么?
答案 0 :(得分:1)
恢复的延续具有原始的r和n 延续,其值不会被两组改变! 应用
都能跟得上;那是重要的一部分;值的更改可见。他们没有重置。我不确定这个问题是否应该被认为是重复的,但是这也出现在call-with-current-continuation - state saving concept中,提问者注意到了(查看整个上下文的问题):
接下来调用3次会产生0,1和'完成。这意味着当状态使用生成器给出的函数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
另见: