现代延续运算符是关于什么的?

dfe*_*uer 11 scheme continuations haskell functional-programming delimited-continuations

回到那天,我虽然明白了call/cc。这些天我看到了更多对“分隔”延续运算符的引用,它们似乎成对出现,如shift/ resetprompt/ control,有时还有更奇特的。但我还没有看到任何基础知识的明确解释,所以

  1. 他们在做什么?
  2. 它们是为了什么?
  3. 什么可能使一组运算符比另一组更适合特定语言/上下文/目的?

ali*_*oar 3

我读过几篇文章,我可以解释这个想法。所以我不知道如何实现它以及如何实际使用它,但我理解主要思想。

假设你有一个像这样的电话

 (f (h (g x)) 2)
^     << scheme undelimited cont. captures from here 
Run Code Online (Sandbox Code Playgroud)

g捕获延续。

  1. 在方案中,如果您调用call/ccinside g,它将复制从顶层开始的所有执行堆栈(从f调用的点开始)——如果您在顶层有许多表达式,每个表达式都会有自己的堆栈,并且调用保存的延续将在顶层停止(因此,在上面的表达式中,它将在 f 之后停止,此时它的值为f)。

  2. 如果您希望从内部捕获延续g直到 的退出点h,并且延续的每次调用都向 f 返回一个值,那么捕获从 的调用点开始的堆栈就足够了h,而不是捕获 的完整堆栈的调用f,因此您想告诉系统调用类似 call/cc 的函数不要从顶层复制其余计算,而是从给定点复制计算,并每次返回该点的值:

    (f (h (g x)) 2)
    
       ^        << delimited cont. captures from here 
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下,您可以对系统进行检测,例如:

    (f (shift (h (g x)) 2))
    
    Run Code Online (Sandbox Code Playgroud)

    并在需要捕获延续的地方调用resetinside 。g

  3. 定界连续可以通过无定界连续来模拟,但我认为在某些情况下能够使用定界更实用。因此,您不能以仅在感兴趣的区域复制堆栈的实际方式在方案中执行此操作,它迫使您复制完整的堆栈(我说“堆栈”而不是堆栈,因为真正的堆栈更大,并且外部堆栈更大)链式堆栈表示退出代码时执行的初始化代码的延续)。

这些是我从读过的论文中收集到的一些想法。我也有兴趣听到更详细的答案。