"continuation prompt?" 到底是什么
What exactly is a "continuation prompt?"
我正在尝试破译the documentation
call-with-continuation-prompt
Applies proc
to the given arg
s with the current continuation extended by a prompt. The prompt is tagged by prompt-tag
, which must be a result from either default-continuation-prompt-tag
(the default) or make-continuation-prompt-tag
. The result of proc
is the result of the call-with-continuation-prompt
call.
我理解它说 "Applies proc
to the given arg
s with the current continuation" 的部分,然后它只是胡言乱语。
延续是什么意思 "extended," 以及 "prompt" 如何做到这一点 "extending?"
从概念上讲,什么是提示?
Scheme 通常具有 continuations 的想法,但 Racket 将其扩展为 delimited continuations 的想法。延续的想法是它捕获剩余的计算以供评估。我不会尝试解释一般的延续,因为这超出了这个问题的范围。
但是,我将解释 delimited continuations 的特殊之处。通常,捕获延续会捕获 整个 计算,一直到顶层。这使得它们在实现复杂控制结构方面的使用相对受限,因为应用延续将完全释放对程序执行的控制。
使用定界延续,您只能捕获延续的特定部分。实际捕获的评估部分由 prompts 分隔,其作用类似于当前延续的标记,指定要捕获多少延续。
好的,但这意味着什么?
与未定界延续相比,如果没有实际看到它的实际应用,定界延续的概念并不是很清楚。
标准(非定界)延续
考虑以下示例代码。
(define *k* #f)
(sqrt
(+ 1 2 3
(call/cc
(λ (k)
(set! *k* k)
0))))
此代码非常简单 — 它捕获延续并存储到全局绑定 *k*
。延续本身看起来像这样:
(sqrt (+ 1 2 3 _))
(其中_
表示调用continuation时要填写的"hole"。)
应用这一延续将如预期的那样精确地工作。
> (*k* 3) ; evaluates (sqrt (+ 1 2 3 3))
3
这一切都很普通。那么定界延续引入的区别是什么?
定界延续
如果我们只想捕获 *k*
中延续的 部分 怎么办?例如,如果我们只想捕获这个延续怎么办?
(+ 1 2 3 _) ; the inner portion of the last continuation
我们可以通过建立一个延续提示来做到这一点,这将调整实际捕获的延续部分。
(sqrt
(call-with-continuation-prompt
(λ ()
(+ 1 2 3
(call/cc
(λ (k)
(set! *k* k)
0))))))
现在,应用 *k*
得到内部结果:
> (*k* 3)
9
定界延续的类比
Continuations 可以 是一个有点抽象的概念,所以如果上面的代码示例不是很清楚,请考虑这个类比。
评估模型是一个堆栈——每个函数调用都会将一个新帧压入堆栈,并从函数返回时将该帧弹出堆栈。我们可以将调用堆栈可视化为一叠卡片。
通常情况下,当捕获延续时,它会捕获当前帧和所有它下面的帧,如下图所示。
未捕获以蓝色表示的顶级。它实际上是分隔系统中的默认提示。
但是,安装新提示会在帧之间创建一种透明分隔线,这会影响将哪些帧捕获为延续的一部分。
此分隔符分隔 延续的范围。
附录:提示标签和延续障碍
这是定界延续的基础知识,但还有其他方法可以控制延续,为延续系统提供更多功能(以及保护它免受恶意代码的侵害),这些是提示标记和延续障碍。
提示标记 的想法本质上是标记给定提示的 "label"。使用上面的卡片类比,可以为每个透明分隔器指定一个标签。然后,当您捕获延续时,您可以指定一直捕获到那个 特定标签 ,即使中间有其他提示和其他标签。
另一方面,继续障碍是一种安全措施。就像提示一样,它们可以可视化为 "dividers" 位于调用堆栈的元素之间,但它们不是用作控制捕获多少堆栈的标记,而是用作防止连续跳跃的守卫 "through"屏障.
有关这方面的更多详细信息,请考虑阅读 the section in the Racket reference on continuation barriers。以下是摘录:
Specifically, a continuation can be replaced by another only when the replacement does not introduce any continuation barriers. It may remove continuation barriers only through jumps to continuations that are a tail of the current continuation. A continuation barrier thus prevents “downward jumps” into a continuation that is protected by a barrier.
我正在尝试破译the documentation
call-with-continuation-prompt
Applies
proc
to the givenarg
s with the current continuation extended by a prompt. The prompt is tagged byprompt-tag
, which must be a result from eitherdefault-continuation-prompt-tag
(the default) ormake-continuation-prompt-tag
. The result ofproc
is the result of thecall-with-continuation-prompt
call.
我理解它说 "Applies proc
to the given arg
s with the current continuation" 的部分,然后它只是胡言乱语。
延续是什么意思 "extended," 以及 "prompt" 如何做到这一点 "extending?"
从概念上讲,什么是提示?
Scheme 通常具有 continuations 的想法,但 Racket 将其扩展为 delimited continuations 的想法。延续的想法是它捕获剩余的计算以供评估。我不会尝试解释一般的延续,因为这超出了这个问题的范围。
但是,我将解释 delimited continuations 的特殊之处。通常,捕获延续会捕获 整个 计算,一直到顶层。这使得它们在实现复杂控制结构方面的使用相对受限,因为应用延续将完全释放对程序执行的控制。
使用定界延续,您只能捕获延续的特定部分。实际捕获的评估部分由 prompts 分隔,其作用类似于当前延续的标记,指定要捕获多少延续。
好的,但这意味着什么?
与未定界延续相比,如果没有实际看到它的实际应用,定界延续的概念并不是很清楚。
标准(非定界)延续
考虑以下示例代码。
(define *k* #f)
(sqrt
(+ 1 2 3
(call/cc
(λ (k)
(set! *k* k)
0))))
此代码非常简单 — 它捕获延续并存储到全局绑定 *k*
。延续本身看起来像这样:
(sqrt (+ 1 2 3 _))
(其中_
表示调用continuation时要填写的"hole"。)
应用这一延续将如预期的那样精确地工作。
> (*k* 3) ; evaluates (sqrt (+ 1 2 3 3))
3
这一切都很普通。那么定界延续引入的区别是什么?
定界延续
如果我们只想捕获 *k*
中延续的 部分 怎么办?例如,如果我们只想捕获这个延续怎么办?
(+ 1 2 3 _) ; the inner portion of the last continuation
我们可以通过建立一个延续提示来做到这一点,这将调整实际捕获的延续部分。
(sqrt
(call-with-continuation-prompt
(λ ()
(+ 1 2 3
(call/cc
(λ (k)
(set! *k* k)
0))))))
现在,应用 *k*
得到内部结果:
> (*k* 3)
9
定界延续的类比
Continuations 可以 是一个有点抽象的概念,所以如果上面的代码示例不是很清楚,请考虑这个类比。
评估模型是一个堆栈——每个函数调用都会将一个新帧压入堆栈,并从函数返回时将该帧弹出堆栈。我们可以将调用堆栈可视化为一叠卡片。
通常情况下,当捕获延续时,它会捕获当前帧和所有它下面的帧,如下图所示。
未捕获以蓝色表示的顶级。它实际上是分隔系统中的默认提示。
但是,安装新提示会在帧之间创建一种透明分隔线,这会影响将哪些帧捕获为延续的一部分。
此分隔符分隔 延续的范围。
附录:提示标签和延续障碍
这是定界延续的基础知识,但还有其他方法可以控制延续,为延续系统提供更多功能(以及保护它免受恶意代码的侵害),这些是提示标记和延续障碍。
提示标记 的想法本质上是标记给定提示的 "label"。使用上面的卡片类比,可以为每个透明分隔器指定一个标签。然后,当您捕获延续时,您可以指定一直捕获到那个 特定标签 ,即使中间有其他提示和其他标签。
另一方面,继续障碍是一种安全措施。就像提示一样,它们可以可视化为 "dividers" 位于调用堆栈的元素之间,但它们不是用作控制捕获多少堆栈的标记,而是用作防止连续跳跃的守卫 "through"屏障.
有关这方面的更多详细信息,请考虑阅读 the section in the Racket reference on continuation barriers。以下是摘录:
Specifically, a continuation can be replaced by another only when the replacement does not introduce any continuation barriers. It may remove continuation barriers only through jumps to continuations that are a tail of the current continuation. A continuation barrier thus prevents “downward jumps” into a continuation that is protected by a barrier.