Scheme “a”究竟是什么;继续提示?“;

Scheme “a”究竟是什么;继续提示?“;,scheme,racket,continuations,delimited-continuations,Scheme,Racket,Continuations,Delimited Continuations,我在试着破译 连续提示呼叫 将proc应用于给定的args,并通过提示扩展当前的延续。提示符由提示符标记标记,该标记必须是默认延续提示符标记(默认)或生成延续提示符标记的结果。proc的结果是带有持续提示的调用的结果 我理解其中的部分,它说“将proc应用到给定的args,并使用当前的继续符”,然后它就开始胡言乱语了 继续被“扩展”意味着什么,“提示”是如何“扩展”的?从概念上讲,什么是提示? Scheme一般都有延续的概念,但Racket通过分隔延续的概念扩展了这一概念。延拓的思想是,它捕获剩

我在试着破译

连续提示呼叫
proc
应用于给定的
arg
s,并通过提示扩展当前的延续。提示符由
提示符标记标记
,该标记必须是
默认延续提示符标记
(默认)或
生成延续提示符标记
的结果。
proc
的结果是带有持续提示的
调用的结果

我理解其中的部分,它说“将
proc
应用到给定的
arg
s,并使用当前的继续符”,然后它就开始胡言乱语了

继续被“扩展”意味着什么,“提示”是如何“扩展”的?

从概念上讲,什么是提示? Scheme一般都有延续的概念,但Racket通过分隔延续的概念扩展了这一概念。延拓的思想是,它捕获剩下的要计算的计算。我不打算一般地解释延续,因为这超出了这个问题的范围

然而,我将解释是什么使分隔的连续体特别。通常,捕获一个延续会捕获整个计算,一直到顶层。这使得它们在实现复杂控制结构时的使用相对有限,因为应用延续将完全释放对程序执行的控制

使用分隔的延续,您只能捕获延续的特定部分。实际捕获的求值部分由提示分隔,这些提示的作用类似于当前继续上的标记,指定要捕获的继续部分的数量

好吧,但这是什么意思? 与不受限制的连续性相比,如果没有实际看到它的作用,分隔连续性的概念就不是很清楚

标准(非分隔)连续体 考虑下面的示例代码

(define *k* #f)

(sqrt
 (+ 1 2 3
    (call/cc
     (λ (k)
       (set! *k* k)
       0))))
这段代码非常简单,它捕获一个延续并存储到全局绑定
*k*
。延续本身如下所示:

(sqrt (+ 1 2 3 _))
(其中,
表示调用continuation时要填充的“洞”。)

应用这种延续将完全如人们所期望的那样起作用

> (*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
分隔连续体的类比

延续可以是一个抽象的概念,所以如果上面的代码示例不完全清楚,请考虑这个类比。

求值模型是一个堆栈,每个函数调用都会将一个新帧推送到堆栈上,然后从函数返回时会将该帧弹出堆栈。我们可以将调用堆栈可视化为一堆卡片

通常,当捕获一个延续时,它会捕获当前帧及其下的所有帧,如下所示

以蓝色表示的顶层不会被捕获。它实际上是分隔系统中的默认提示

但是,安装新的提示会在帧之间创建一种透明的分隔符,这会影响作为延续的一部分捕获的帧

此分隔符限定了延续的范围

附录:提示标签和延续屏障 这是分隔连续性的基础,但还有其他控制连续性的方法,它们为连续性系统提供了更强大的功能(以及保护其免受恶意代码的攻击),这些方法是提示标记和连续性屏障

提示符标记的概念本质上是标记给定提示符的“标签”。使用上面的卡片类比,可以给每个透明分隔器一个标签。然后,在捕获延续时,可以指定要一直捕获到该特定标签,即使中间有其他带有其他标签的提示

另一方面,持续壁垒是一种安全措施。就像提示一样,它们可以被可视化为位于调用堆栈元素之间的“分隔符”,但它们不是用来控制捕获了多少堆栈的标记,而是用来防止继续跳过“屏障”

有关这方面的更多细节,请考虑阅读。这里有一段摘录:

具体地说,只有在替换不引入任何继续障碍时,才能用另一个继续替换。它只能通过跳转到作为当前延续尾部的延续来消除延续障碍。因此,延续屏障可防止“向下跳跃”进入受屏障保护的延续


你是怎么画这些图形的?当然,你没有时间在Photoshop上手工画出来。@throwawayaccount3000万那正是我做的!我认为,它们的质量很低,因此是可行的PIt会节省我很多时间去了解这些。我通过一次在闭包中包装规则延续来实现这个概念。调用闭包时,闭包会将自己的继续传递回原始继续,从而完全产生分隔继续的效果。