论坛首页 综合技术论坛

Lua 的协同和 Scheme 的延续

浏览 3351 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-02-01  

我记得某期《程序员》在介绍 Lua 时说“Lua 的协同程序类似 Scheme 的延续,只是自由度更高。”。我认为这样的说法是欠妥的,因为事实上协同的能力比延续要弱。

首先来看下延续。理论上,延续是这样一种编程风格:对于每个函数,增加最后一个延续参数,所有的函数都不返回值,而把返回值作为参数传给延续参数。这样一来,建立延续标记的函数(如 call/cc)就可以获取调用路径中任何一个标记,并把它绑定到自己的参数函数的第一个参数上。看到 Scheme 的 call/cc,知道的人都会会心一笑,因为他古怪的标记绑定方法正是最初 lambda 演算隐藏掉所有的延续参数后的结果。实际上,延续为每个要标记的调用点在栈上都做了标记,使得调用路径上的函数可以跨越闭包设定的返回路径返回值到任意一个标记上。

再来看协调程序。协同程序事实上是弱化了的延续。它只能标记出一个函数前一次延续绑定的位置,也就是说,对于某个调用路径上的函数来说,它最多只能跳回到上一次绑定的返回出口上。协同的能力介于正常返回值和延续之间。

那么 Lua 这样做有什么意义呢?意义还是有的。一方面,真正标记出所有的位置是一个正常的编译器不可能做的事情。完全支持延续的编译器都对延续进行了大量优化,而且如果是较纯的函数式编程语言,还在闭包变换时可以消去对某些函数而言达不到的延续。但 Lua 虽然在支持 FP 方面比 Ruby,Python 之流做得更加出色,但本质上还是命令式语言,做这样的优化代价太大;另一方面,Scheme 是追求完备性的语言,需要用延续来辅助程序逻辑;Lua 因为是命令式语言,已经提供了不错的异常处理和生成器支持,也就是说延续能实现的主要的流程控制都以实现,完全实现延续以支持函数风格的自动回溯不再值得,Lua 只需要一个能够产生瘦线程的特性即可,不想要在函数间逻辑地、合理地任意跳转的能力,而协同就可以做到;最后一点,延续本身存在安全跟踪延续路径和清理上的困难(为此 Scheme 还额外提供了 dynamic-wind 来限制延续在闭包之外的重复跳转),为简化程序员的工作,增加限制不正是 RoR 等成功例子所颂扬的“约定大于配置”的金科玉律吗?
   发表时间:2008-02-02  
Lich_Ray和lichray是啥关系?
0 请登录后投票
   发表时间:2008-02-02  
林杰杰 写道
Lich_Ray和lichray是啥关系?

很明显,大号和小号的关系。前者赚分,后者瞎掰,工作娱乐两不误
0 请登录后投票
   发表时间:2008-02-18  
明显coroutine比call/cc流行啊。js2都要加入coroutine了。
0 请登录后投票
   发表时间:2008-02-18  
hax 写道
明显coroutine比call/cc流行啊。js2都要加入coroutine了。

那是当然的。因为还有很重要的一点我忘了说了:延续产生并发还需要手动控制或者语法支持,而协同已经是修改过的版本了,已启动就相当于已经对所有协同插入了相互调用代码,已经是并发的了,很是方便啊。

PS: JS2 那个死家伙让它去死吧,史上最蔚为壮观的语言:使用操作语义描述,不完全(而且很不完全,大量特性而且是很“重要”的特性还在待考列表里)手册写了四五百页。一群觉得乱添特性很好玩的傻X 。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics