作者: Denys Duchier 翻译: Shining Ray @ Nirvana Studio 写本文旨在回应comp.lang.python新闻组中关于延续的讨论。 对于call/cc(call with current continuation)的情结和关于他的操作解释粗糙的细节内容,至今一直掩盖了延续的简洁和优雅。在本文中,我想用两个方式来纠正这个问题: 首先用一个简单且直观的方式展示延续的概念。 第二通过提供_可运行的_Python代码,来描述如何使用延续而不用call/cc来实现搜索引擎。 我将展示: 一个针对命题公式确定性检查工具。 一个基本的带回溯和裁剪的prolog引擎。 我希望这能帮助那些对于这个论题有些迷惑的人搞清这个问题。我还想指出上面讲到的两个程序是我在今天晚上花了几个小时写的,他们应该可以给你关于下面将要讲述的技术的能力的一些衡量尺度。 1. 简化延续 习惯上一般来说,一个函数返回一个值是这样的: def foo(x): return x+1 这隐含了它的值返回的地方。而延续的想法是通过添加一个延续参数来明确要返回的地方。函数不“返回”值,而是通过把值作为一个参数传递给延续“继续”处理值。在基于延续的程序中,以上函数foo变成了: def foo(x,c): c(x+1) 从这个角度看,函数从不使用返回“return”。取代的是它“继续”。正因为这个原因,延续有时候会被描述为“带参数的goto”。 上面描述的想法是。更精确地说,它是CPS(Continuation Passing Style,延续传送风格)的一个初步代码转换。基本的想法是给每个函数添加一个额外的“延续”参数,并进一步转化函数体以便不用返回他的值,而是把值传送给这个额外的延续参数。 在foo函数的例子中已经大体描述了这个概念。然而,更确切的,要注意CPS转换同时展开了所有的非lambda算子的嵌套表达式(换句话说,就是他显式地连接了所有子表达式的计算)。让我们看一个例子: def baz(x,y): return 2*x+y 在延续传送的观点中,甚至像*和+之类的基本操作符都要带一个额外的延续参数。我们通过以下定义进行模拟: def add(x,y,c): c(x+y) def mul(x,y,c): c(x*y) 现在,CPS可以把上面的baz函数转换成: def baz(x,y,c): mul(2,x,lambda v,y=y,c=c: add(v,y,c)) 换句话说,2*x的计算现在使用了一个延续来接收结果v并使用它来计算 v+y并最终把这个结果传给总的延续c。 [...]
关于我
- 曹力
- 程序员 / 架构师
- JavaScript高级程序设计译者
- NirvanaStudio精神领袖
版权声明
本 Blog 所有文章若无特别声明都遵循创作共用约定,要求署名、非商业、保持一致。转载时请先阅读以上许可协议,并以超链接形式注明出处。分类目录
-
RSS Links
Blogroll
Nirvana Studio
其他
标签
功能
-
