|
|
1
41
想象一下,如果程序中的每一行都是单独的函数。每个函数都接受下一行/下一个要执行的函数作为参数。 使用这个模型,您可以在任何一行“暂停”执行,稍后再继续执行。您还可以做一些创造性的事情,例如临时跳上执行堆栈以检索值,或者将当前执行状态保存到数据库以供以后检索。 |
|
|
2
11
你可能比你想象的更了解他们。 例外是“仅向上”延续的一个例子。它们允许代码深入堆栈调用异常处理程序来指示问题。 Python示例:
生成器是“仅向下”延续的示例。例如,它们允许代码重新输入一个循环来创建新的值。 Python示例:
在这两种情况下,它们都必须被特别地添加到语言中,而在具有连续性的语言中,程序员可以在它们不可用的地方创建这些东西。 |
|
|
3
9
A抬头一看,这个例子既不简洁也不特别清楚。这是一个强大的延续应用程序的演示。作为一个VB/ASP/C程序员,您可能不熟悉系统堆栈或保存状态的概念,所以这个答案的目标是演示而不是解释。 延续非常通用,是保存执行状态并稍后恢复的一种方法。下面是一个在Scheme中使用continuations的协作多线程环境的小例子: (假设在未在此处定义的全局队列上,排队和出列操作按预期工作)
这提供了一个函数可以使用的三个动词-fork、context switch和end process。fork操作分叉线程,并在一个实例中返回t,在另一个实例中返回f。上下文切换操作在线程之间切换,结束进程终止线程。 以下是它们的使用示例:
输出应该是
在一个类中学习过分叉和线程的人通常会得到类似的例子。本文的目的是证明通过继续,您可以通过手动保存和恢复单个线程的状态(继续),在单个线程内实现类似的结果。 另外。-我想我在Lisp上还记得类似的东西,所以如果你想看专业代码,你应该看看这本书。 |
|
|
4
7
认为延续的一种方法是作为处理器堆栈。当您“用当前的延续c调用”时,它调用您的函数“c”,并且传递给“c”的参数是您当前的堆栈,上面有您所有的自动变量(作为另一个函数表示,称之为“k”)。同时,处理器开始创建新的堆栈。当您调用“k”时,它会在原始堆栈上执行“从子例程返回”(RTS)指令,将您跳转回原始“当前继续调用”(“从现在起调用cc”)的上下文,并允许您的程序像以前一样继续。如果您将参数传递给“k”,那么这将成为“call cc”的返回值。 从原始堆栈的角度来看,“call cc”看起来像正常的函数调用。从“c”的角度来看,原始堆栈看起来像一个永远不会返回的函数。 有一个古老的笑话,讲的是一个数学家爬进笼子,把它锁起来,然后宣称自己在笼子外面,而其他一切(包括狮子)都在笼子里面,从而把一头狮子抓进笼子里。延续有点像笼子,“c”有点像数学家。你的主程序认为“c”在里面,“c”认为你的主程序在“k”里面。 您可以使用continuations创建任意的控制结构流。例如,您可以创建线程库。”yield“使用”call cc“将当前的延续放在队列上,然后跳到队列头上的延续。信号量也有它自己的暂停延续队列,线程通过将其从信号量队列中取出并放到主队列中来重新调度。 |
|
|
5
4
基本上,延续是一个函数停止执行,然后在稍后某个时间点从停止的地方恢复的能力。在C中,您可以使用yield关键字来执行此操作。如果你愿意的话,我可以更详细地讲,但你需要一个简明的解释。;-) |
|
|
6
2
我仍在“习惯”延续,但我认为有一种方法可以用来思考它们,那就是将程序计数器(PC)概念抽象化。一台PC机“指向”下一条要在内存中执行的指令,但当然,指令(以及几乎所有的指令)隐式或显式地指向后面的指令,以及服务中断的任何指令。(即使noop指令也会隐式跳转到内存中的下一条指令。但如果发生中断,通常需要跳转到内存中的其他指令。) 在某种意义上,程序内存中的每个潜在的“活动”点(控件可能在任何给定点跳转到该点)都是活动的延续。可以达到的其他点是潜在的活动延续,但更确切地说,它们是由于达到一个或多个当前活动延续而潜在“计算”的延续(可能是动态的)。 在传统的连续性介绍中,这似乎有点不合时宜,其中所有挂起的执行线程都显式地表示为静态代码的连续性;但它考虑到了这样一个事实:在通用计算机上,PC指向的指令序列可能会改变内存表示的内容。重新发送该指令序列的一部分,从而实质上创建了一个新的(或修改过的,如果您愿意的话)动态延续,这个延续在创建/修改之前的延续激活中并不存在。 因此,延续可以被视为PC的高级模型,这就是为什么它在概念上包含普通的过程调用/返回(就像古代的Iron一样,通过低级跳转进行过程调用/返回,又称Goto、指令加上对PC调用的记录和返回时的恢复)以及异常、线程、协程等。 因此,正如PC指出“未来”将要发生的计算一样,延续也会做同样的事情,但在更高、更抽象的层次上。PC隐式地引用内存加上所有内存位置和寄存器“绑定”到任何值,而延续则通过语言适当的抽象来表示未来。 当然,虽然每台计算机(核心处理器)通常只有一台PC,但实际上有许多“活跃的”PC-ish实体,正如上面提到的那样。中断向量包含一束,堆栈更多,某些寄存器可能包含一些,等等。当它们的值被加载到硬件PC时,它们被“激活”,但是连续性是概念的抽象,而不是PC或它们的精确等价物(尽管我们经常认为和用这些术语编写代码,使事情相当简单)。 本质上,延续是“当被调用时下一步要做什么”的一种表示,因此,可以是(并且,在某些语言和延续传递式程序中,通常是)一个被实例化、传递和丢弃的一级对象,就像大多数其他数据类型一样,非常类似于经典计算机如何处理内存位置。 视界 PC——几乎可以与普通整数互换。 |
|
|
7
2
在C中,您可以访问两个延续。一个,通过
有些语言允许您将这些语句视为第一类值,因此您可以分配它们并在变量中传递它们。这意味着你可以储存
这在很多情况下都很方便。有一个例子与上面的例子类似,你想暂停你正在做的工作,然后在发生某些事情时(比如收到一个Web请求,或者其他事情)继续它。
我在几个项目中使用它们。在一个例子中,我使用它们,这样我就可以在网络上等待IO时暂停程序,然后稍后再继续。在另一种语言中,我编写了一种编程语言,在这种语言中,我允许用户访问作为值的延续,这样他们就可以编写
|
|
|
8
1
想想线程。线程可以运行,您可以得到它的计算结果。延续是可以复制的线程,因此可以运行相同的计算两次。 |
|
|
9
1
连续性重新引起了Web编程的兴趣,因为它们很好地反映了Web请求的暂停/恢复特性。服务器可以构造表示用户会话的Continuation,并在用户继续会话时继续。 |