什么决定了Scheme延续的外部边界?
延续的解释通常说延续代表“程序的其余部分”(或类似的措辞)。但显然有一个边界,在这个边界上,继续停止收集这些剩余的计算步骤。那边界是什么?程序的最高级别?或者是其他东西?
这些解释往往以这样的玩具示例开始。
(+ 1 (call/cc
(lambda (cc)
(cc 2))))
这计算为3因为(cc 2)意味着“放入2由call/cc形式雕刻而成的表达式中的孔中” 。表达式变为(+ 1 2),又名3。
现在考虑这个例子:
(define lc #f)
(+ 1 (call/cc
(lambda (cc)
(set! lc cc)
(cc 2))))
(displayln "done")
(lc 42)
在这里,我们将延续存储cc在变量 中lc。在计算表达式后,我们done再次显示并使用延续作为(lc 42)。我们得到什么?
3
done
43
3
done
43
但为什么?如果延续是“程序的其余部分”,为什么延续不捕获 之后发生的所有事情call/cc,包括对displayln和的后续调用lc?在这种解释下,延续将创建一个无限循环。
很明显,事实并非如此。相反,延续似乎正在捕获程序的其余部分,直到它到达随后的表达式,它会忽略(以及任何其他表达式)。
但现在考虑这个例子:
这种情况下的结果是:
3
done
outer
43
done
意思是,延续确实捕获了(displayln "done")in f,尽管它仍然没有捕获(displayln "outer")和(lc 42)的调用之后f。
最后一个例子——我们将所有内容都移动到一个新函数中g:
(define lc #f)
(define (f)
(displayln (+ 1 (call/cc
(lambda (cc)
(set! lc cc)
(cc 2)))))
(displayln "done"))
(f)
(displayln "outer")
(lc 42)
这一次,我们得到了前面例子中预测的无限循环:
3
done
outer
43
done
outer
43
···
所以最初的直觉并不完全偏离基础。这只是顶级无望的另一个例子吗?或者是否有更简洁的解释来说明延续的范围?