Block And Closure, Ruby VS Groovy

| |
[晴 2009/04/09 14:34 | by xeric ]
问题从一个Groovy迭代开始:
def a = 1..9
a.each{
 println it
}

这种简单的迭代work的很完美,但我想改一下需求,只打印等于4的数字
def a = 1..9
a.each{
 if(it == 4){
   println it
 }
}

似乎也正常,但是,其实这边打印了4之后的迭代就没必要执行了,如果是ruby,我会这么做

(1..9).each do i
 if i == 4
   puts i
   break
 end
end

而groovy就不行了,break是不能写入到一个闭包内的
原因也不难发现,groovy的底层是java支持的,那么实现each不用看源码不妨先猜测一下:
each是list的一个meta method,接受一个闭包作为参数。
内部用invoke的方式去把闭包调用起来。
所以这个代码更像是一个封装好的代码块的反射调用,而非逻辑集成,
ruby能工作原因可能是底层中,作为一个闭包并不是简单的block.call或者invoke,
而是编译器已经将其识别为执行流程的一部分,或者说,闭包并没有把逻辑封闭在本身内。
ruby执行码是原始底层支持的
groovy则最终还是java的执行码,这种推断也不是空穴来风,不妨看看一个包含闭包的groovy class编译后的状态:
XXX.class
XXX$_closure1.class
也就是说,闭包也不过是个类而已,因此其中不能添加break来控制调用者本身的流程也可想而知了。
而对于一个block,也就是普通的控制流程{}包起来的流程,比如if else这些包起来的,
则是原生的block,
这点和ruby有着极大的不同,个人认为也影响了程序员的一些第一直觉判断。
而且,如果迭代并不能有效被控制(当然不是绝对,比如continue可以通过return来实现)
那么迭代本身的价值就有所损失,不过真要把闭包trade as block来的话,那groovy底层真的要大手术了。
所以暂时(甚至永远),groovyer必须要把block和closure分分仔细,也不要随便搞乌龙写法出来,
举个例子,试图对一个迭代进行有效选择并返回,恐怕是永远做不到的,安心的for..in吧。

有人说groovy的closure更像是lambda,我觉得挺有道理的,当然,我只了解as和js的lambda,
其他的并不是很了解,我记得Martin Fowler有个介绍closure的文章里面确实也把js的lambda归为js脚本的closure,当然,这个不扯了,概念而已,关键是,要明白怎么用,为什么会这样。

有个很不错的文章,链一下:
http://blog.csdn.net/hax/a...
Tags: , ,
Ruby | 评论(0) | 引用(0) | 阅读(679)
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
昵称   密码   游客无需密码
网址   电邮   [注册]
               

验证码 请输入左侧的字母,不区分大小写