设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 3149|回复: 7

[讨论] 请教for..in和each的区别

[复制链接]

Lv2.观梦者

梦石
0
星屑
790
在线时间
1666 小时
注册时间
2009-7-25
帖子
532

开拓者

发表于 2011-1-19 13:16:42 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
由于习惯用C/C++。。。吾辈喜欢用in来遍历,近来看到很多人都用each呢(尤其是67前辈。。
想问下这两种语句有什么优劣性呢?

点评

被点名了么  发表于 2011-1-19 17:11
对了分类是不是换成讨论比较好一点。。  发表于 2011-1-19 13:17
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
14 小时
注册时间
2011-1-13
帖子
9
发表于 2011-1-19 13:19:57 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
39352
在线时间
7470 小时
注册时间
2009-7-6
帖子
13482

开拓者贵宾

发表于 2011-1-19 13:40:10 | 显示全部楼层
回复 烁灵 的帖子

回复 烁灵 的帖子

for 和each个人认为差不多
for是ruby自带语法
each是一个带块的方法,可以循环对象,一般是隶属于Proc类,也可以用Kernel的lambda函数
自己想像的伪代码:
  1. def each(str,&block)
  2.   block.call(str)
  3. end
复制代码

点评

受教。  发表于 2011-1-21 10:17
除非需要保存闭包留待他用,否则没有必要把和方法关联的块转换为 Proc 对象(这种情况下块只依赖于方法的局部上下文)=)  发表于 2011-1-21 10:16
由于自己也在学习阶段,以上言论均是个人理解.不代表就是正确的.  发表于 2011-1-19 13:43
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
790
在线时间
1666 小时
注册时间
2009-7-25
帖子
532

开拓者

 楼主| 发表于 2011-1-19 14:21:22 | 显示全部楼层
回复 fux2 的帖子

说起来,{}好奇里边的东西是怎么被赋值的,ruby可以传引用么?
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
39352
在线时间
7470 小时
注册时间
2009-7-6
帖子
13482

开拓者贵宾

发表于 2011-1-19 14:27:47 | 显示全部楼层
回复 烁灵 的帖子

{}包括的部分是块代码
比如
  1. def fux2
  2.   yield if defined? yield
  3. end
复制代码
方法,
执行
  1. fux2{p "rpg.blue"}
复制代码
就会执行块里的代码

点评

恩,yield的这个举例还是不错的,话说自制迭代器的yield有点看不懂的说,这下懂了。感谢。  发表于 2011-1-19 14:49
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
7926
在线时间
1181 小时
注册时间
2007-7-29
帖子
2055
发表于 2011-1-19 15:20:38 | 显示全部楼层
each只是针对obj里所有的元素,相对for是循环。
each的处理因为省了一些阶段所以较快。

点评

还有一个挺雷人的,each是传递value parameter,这点之前测试时才测试出来,汗死无数人。  发表于 2011-1-21 00:45
回复 支持 反对

使用道具 举报

Lv1.梦旅人

旅之愚者

梦石
0
星屑
240
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

发表于 2011-1-21 00:29:36 | 显示全部楼层
本帖最后由 六祈 于 2011-1-21 00:35 编辑

回复 fux2 的帖子

fux君这个例子欠妥
愚者猜测你想表达,如果有代码块,则执行代码块,对吗?

如果是这样的话,应该是yield if block_given?

点评

0.0咱一直这么用的.  发表于 2011-1-21 07:09
根据测试结果来看是一样的,defined?还有这样的妙用  发表于 2011-1-21 00:38
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
发表于 2011-1-21 01:24:42 | 显示全部楼层
本帖最后由 苏小脉 于 2011-1-21 01:32 编辑

Ruby 内置的循环结构只有 while 和 until 两种,for ... in ... 基本上可以看作是 Ruby 的语法糖,它最终会发送调用 each 方法的消息给 in ... 后面的对象。这其实也是为了减少模块的耦合而实现的——想要进行迭代的人不需要知道将要迭代的结构,就能实现迭代。所以,通过 Ruby 的鸭子类型,for ... in ... 或者直接调用 each 都不需要保证将要迭代的结构的运行时类型是可迭代的,只要它能响应 each 方法,它就是可以迭代的。所以在目的上 for ... in ... 和 each 没有区别。

这俩唯一的一个区别是局部变量的词法作用域的差异。for ... in ...,包括 while 和 until,都是语法糖,是不会产生新的作用域的,所以循环外部的变量可以在内部引用,而内部创建的局部变量对外也是可见的。each 则不同,由于其循环主体是在 Ruby 的块中,而块是拥有自己的作用域的,所以就有了差别。在块中创建的局部变量对外是不透明的:
  1. [1].each do
  2.     i = 2
  3. end

  4. p i # error
复制代码
除非在这个 each 的块的词法范围之外也出现了一个 i = 的赋值语句,这个判定是在词法分析时,一旦被 Ruby 词法分析器看见就知道是局部变量,并不一定要执行:

  1. if false
  2.     i = 1
  3. end

  4. [1].each do
  5.     i = 2
  6. end

  7. p i # OK
复制代码
效率上——对于,Ruby 1.8 得看具体解释器是如何处理的,理论上由于是直接在抽象文法树上求值,两者在文法分析时都会被剖析为一样的文法树节点,所以在执行时都没有区别,区别应该在于局部变量的创建,这个可以通过 1.9 YARV 编译 Ruby 代码后的指令来分析:

  1. [1].each do
  2. end
复制代码
这一段反汇编后是:

  1. |------------------------------------------------------------------------
  2. 0000 trace            1                                               (   1)
  3. 0002 duparray         [1]
  4. 0004 send             :each, 0, block in <compiled>, 0, <ic:0>
  5. 0010 leave
  6. == disasm: <RubyVM::InstructionSequence:block in <compiled>@<compiled>>=
  7. == catch table
  8. | catch type: redo   st: 0000 ed: 0001 sp: 0000 cont: 0000
  9. | catch type: next   st: 0000 ed: 0001 sp: 0000 cont: 0001
  10. |------------------------------------------------------------------------
  11. local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1] s3)
  12. [ 2] i<Arg>
  13. 0000 putnil                                                           (   2)
  14. 0001 leave
复制代码
而如果是:

  1.     for i in [1]
  2.     end
复制代码
反汇编后:

  1. local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
  2. [ 2] i
  3. 0000 trace            1                                               (   1)
  4. 0002 duparray         [1]
  5. 0004 send             :each, 0, block in <compiled>, 0, <ic:0>
  6. 0010 leave
  7. == disasm: <RubyVM::InstructionSequence:block in <compiled>@<compiled>>=
  8. == catch table
  9. | catch type: redo   st: 0005 ed: 0006 sp: 0000 cont: 0005
  10. | catch type: next   st: 0005 ed: 0006 sp: 0000 cont: 0006
  11. |------------------------------------------------------------------------
  12. local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1] s3)
  13. [ 2] ?<Arg>
  14. 0000 getdynamic       *, 0                                            (   2)
  15. 0003 setlocal         i                                               (   1)
  16. 0005 putnil                                                           (   2)
  17. 0006 leave
复制代码
可见 Ruby 在处理 for 循环的循环局部变量 i 时,是需要额外的指令周期的。同时,由于它的生命周期比块内部处理的变量(|i|)的长,那么如果这段代码定义在顶层,即使循环结束了,i 也不会被回收的。

点评

不能说是 each 有作用域,只能说是 Ruby 的块有。  发表于 2011-1-23 00:39
就是这个,我之前还以为each没有作用域,知道几个月前也做了这个测试才知道。==  发表于 2011-1-23 00:09
啊咧……汇编语音不懂……  发表于 2011-1-21 07:10
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-3-29 00:26

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表