我有以下 Scheme 程序:
(define sg-pair (let ()
(define x #f)
(cons
(call/cc (lambda (c)
(set! x c)))
x)))
(display sg-pair)
(display "\n")
(if (eq? (car sg-pair) (void))
(let ()
((cdr sg-pair) "first")))
(if (string? (car sg-pair))
(let ()
((cdr sg-pair) 2)))
这将打印以下内容:
(#!void . #<procedure #2>)
(first . #<procedure #2>)
(2 . #<procedure #2>)
我目前对于如何构建这一对的理解是:
- 延续 (
c
) 在调用 时创建call/cc
。此时,x
是#f
,并且尚未被评估为 的第二个参数cons
。 lambda
在传递给的的执行期间call/cc
,x
被设置为非 false(继续)值。call/cc
自然返回,并且不返回任何内容(#!void
),并且x
从之前的 set 调用中检索到。- 当后续调用通过 检索的延续时
cdr
,我期望在创建延续时已知的 的映射x -> #f
被恢复。然后,由于lambda
的主体call/cc
不会再次运行,因此x
将保持为 false。 x
将在 之后进行评估call/cc
,这次是#f
,导致第二display
个cdr
不同,并且第二次调用cdr
失败。
x
然而,实际发生的情况是,当重新进入延续时,会记住先前的值。为什么?怎么做?Scheme 实际上使用什么机制来记住环境?