Lua 的协同和 Scheme 的延续

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值