起
随着 nodejs 的兴起,异步编程成为一种潮流,而异步也对编程风格带来了一些影响,典型的比如在客户端尚不明显的 cps 风格的大量出现:
getUser(function(){ // .... getItem(function(){ // ... }); })
回调嵌套带来性能,栈溢出,以及代码阅读上的一系列的问题,目前有不少解决方案,比如 promise 或引入新的编程原语. 但本次要介绍的是在上世纪60年代就提出来的一个概念 continuation,用来解决该问题。
承
continuation 是一种表达范围更广的概念,可用于实现 closure,generator 等动态语言常见的特性,甚至 goto ,而支持的语言也比较少,恰好 rhino 实现了 continuation,因此可以在 javascript 上做下演示,对比下传统的回调实现。
常见应用场景: 异步执行某些操作后再进行返回结构处理,一般实现如下(不解释):
function doSomethingAsynchronously(callback) { var t = new java.lang.Thread(new java.lang.Runnable() { run: function () { try { java.lang.Thread.sleep(1000); } catch (e) { print(e); } callback(1); } }); t.start(); } var cont = doSomethingAsynchronously(function (x) { print(x); });
可以看到已经引入了一个回调函数用来接收异步结果,即 cps 风格。
而如果用 continuation 来实现的话则是另外一种风格:
function makeRequest(cont) { var t = new java.lang.Thread(new java.lang.Runnable() { run: function () { try { java.lang.Thread.sleep(1000); } catch (e) { print(e); } cont(1); } }); t.start(); } function getContinuation() { return new Continuation(); } function doSomethingAsynchronously() { var x = 1; var cont = getContinuation(); if (cont instanceof Continuation) { x = 2; makeRequest(cont); } else { print('run'); cont += x; } return cont; } var cont = doSomethingAsynchronously(); if (typeof cont == 'number') { print(cont); }
其中 new Continuation() 产生一个 continuation 可调用对象,这个对象封装了当前代码执行处以及上下文(注意 rhino 记录的是 new Continuation() 所在函数的位置),当调用 continuation 对象后则相当于一个增强的 goto 调用,回到产生 continuation 对象的调用点,恢复上下文,并把参数值作为 continuation 对象的值后执行。
continuation 不仅可以解决 cps 带来的问题,也可以解决目前 web 开发多页面跳转无状态所带来的逻辑代码分散的问题(个人建议单页面 javascript 控制),在java端有 cocoon 框架(结合 rhino ),可以使用 continuation 记录上下文来达到传统客户端的开发体验:
function calculator() { var a, b, operator; cocoon.sendPageAndWait("getA.html"); a = cocoon.request.get("a"); cocoon.sendPageAndWait("getB.html"); b = cocoon.request.get("b"); cocoon.sendPageAndWait("getOperator.html"); operator = cocoon.request.get("op"); }
转
continuation 虽然有不少优点,但由于过于灵活,强大也会导致一些其他问题,例如 continuation 实现需要比 closure 记录更多的上下文信息,可能会对运行效率造成影响。另外如果滥用会造成 goto 语句一样的问题。
合
continuation 是一个表达力很强的功能,合理利用后能够形成新的编程风格从而改善可读性,维护性等问题,而随着 es6 generator 等的实现,javascript 也将受益。
相关推荐
JooseX.CPS-JavaScript的Continuation Passing Style 实现以及一些语法糖,简化了其在Joose方法和方法修饰符中的使用 概要 独立使用: UI.maskScreen("Please wait") TRY(function (url, data) { XHR....
主要介绍了C#中的递归APS和CPS模式详解,本文讲解了累加器传递模式、CPS函数、CPS变换、CPS尾递归、尾递归与Continuation等内容,需要的朋友可以参考下
dotty-cps-async:Dotty的实验性CPS变压器
CPS:http://en.wikipedia.org/wiki/Continuation-passing_style示例代码使用迭代 + 尾递归。 代码如下:#include typedef void (*END_OF_END)(unsigned long);void fibonacci(int, unsigned long, unsigned long, ...
LISP的基本语法 递归程序结构的基本模式 数据结构与算法 高阶函数 Continuation与CPS 图灵机与停机问题 Y Combinator 语言求值器 所有的这些都是0基础上一步步引导读者去建立的。豆瓣9.3分好评
cps:Nim的连续传递样式:link:
Continuation-Passing Style - 用于 Nim。 在过去的几个月里,观看 Nim 社区的人可能听说过“CPS”这个词。 似乎对 CPS 存在一些混淆。 具体来说,CPS是什么,不是什么,能做什么,不能做什么。 这篇简短的文章试图...
scala-continuations是Scala的编译器插件和库,提供对CPS(连续传递样式)转换的支持。 它不再维护。 过去的发行版(适用于Scala 2.12和更早版本)在Maven Central上仍然可用。 您可能还对感兴趣,它涵盖了曾经是...
2.4 CPS(Continuation-Passing Style) . . . . . . . . . . . . . . . . 16 2.5 函數返回函數與 Currying . . . . . . . . . . . . . . . . . . . . . 17 2.6 流程控制 . . . . . . . . . . . . . . . . . . . ....
延续(解释器以Continuation Passing Style CPS实现) 通过使用蹦床进行尾部呼叫优化 通话/抄送 使用延续进行协作式多任务处理 所有计算都使用多个参数 漂亮的列表打印 带反引号的引号 宏定义和宏扩展 从符号到...
ES6尾调用优化演示使用 Babel 和 Traceur 进行 ES6 尾调用优化的演示查看结果日志: : 简单的尾... : CPS (Continuation Passing Style) => 现在只有 Traceur 可以优化。如何构建git clone 、 npm install和npm test 。
初级java笔试题 编译器、解释器和运行时领域的优秀资源、学习材料、工具、框架、平台、技术和源代码项目的精选列表。...CPS(Continuation Passing Style)。 - 学习构建编程语言背后的模式并使用 ANT
初级java笔试题 编译器、解释器和运行时领域的优秀资源、学习材料、工具、框架、平台、技术和源代码项目的精选列表。 这份清单偏向于教育。...CPS(Continuation Passing Style)。 - 学习构建编程语言背后
具有类别理论基础支持的功能可组合性的连续传递样式(CPS)功能的小巧但功能强大的功能。 npm install cpsfy (或pnpm install cpsfy以节省磁盘空间。) 没有依赖策略。 为了获得最大的安全性,此程序包旨在保持...