“for”和“Ruby”中的“each”
我刚刚有一个关于Ruby中的循环的问题。 这两种迭代方式是否有区别?
# way 1 @collection.each do |item| # do whatever end # way 2 for item in @collection # do whatever end
只是想知道如果这些是完全一样的,或者如果可能有一个微妙的差异(可能当@collection
是零)。
这是唯一的区别:
每:
irb> [1,2,3].each { |x| } => [1, 2, 3] irb> x NameError: undefined local variable or method `x' for main:Object from (irb):2 from :0
对于:
irb> for x in [1,2,3]; end => [1, 2, 3] irb> x => 3
使用for
循环,在块完成之后,迭代器variables仍然存在。 在each
循环中,除非在循环开始之前它已经被定义为局部variables,否则它不会。
除此之外, for
each
方法只是语法糖。
当@collection
nil
两个循环都抛出exception:
例外:对于main:Object,未定义的局部variables或方法`@collection'
请参阅“ For循环的邪恶 ”一个很好的解释(考虑到variables范围,有一个小的区别)。
使用each
被认为是更习惯于使用Ruby。
你的第一个例子,
@collection.each do |item| # do whatever end
比较习惯 虽然Ruby支持像while
和while
这样的循环结构,但块语法通常是首选。
另一个微妙的区别是,你在for
循环中声明的任何variables都可以在循环之外使用,而迭代器中的variables是私有的。
还有一个不同..
number = ["one", "two", "three"] => ["one", "two", "three"] loop1 = [] loop2 = [] number.each do |c| loop1 << Proc.new { puts c } end => ["one", "two", "three"] for c in number loop2 << Proc.new { puts c } end => ["one", "two", "three"] loop1[1].call two => nil loop2[1].call three => nil
来源: http : //paulphilippov.com/articles/enumerable-each-vs-for-loops-in-ruby
为更加清楚: http : //www.ruby-forum.com/topic/179264#784884
它看起来没有区别, for
each
下面。
$ irb >> for x in nil >> puts x >> end NoMethodError: undefined method `each' for nil:NilClass from (irb):1 >> nil.each {|x| puts x} NoMethodError: undefined method `each' for nil:NilClass from (irb):4
就像贝亚德所说的,每一种都比较习惯。 它隐藏了更多的东西,不需要特殊的语言function。 每Telemachus的评论
for .. in ..
设置循环的范围之外的迭代器,所以
for a in [1,2] puts a end
在循环结束后留下a
定义。 哪里没有。 这是另一个赞成使用each
一个的原因,因为临时variables的寿命较短。
据我所知,使用块而不是语言中的控制结构是更习惯的。
永远不要使用它可能会导致错误。
差别是微妙的,但可能会造成巨大的错误!
不要被愚弄,这不是关于惯用代码或风格的问题。 这是避免生产代码中几乎无法追踪的错误的问题。 Ruby的实现有一个严重的缺陷,不应该使用。 始终使用each
循环,永远不要使用循环。
这里是一个例子,介绍一个错误,
class Library def initialize @ary = [] end def method_with_block(&block) @ary << block end def method_that_uses_these_blocks @ary.map(&:call) end end lib = Library.new for n in %w{foo bar quz} lib.method_with_block { n } end puts lib.method_that_uses_these_blocks
打印
quz quz quz
使用%w{foo bar quz}.each { |n| ... }
%w{foo bar quz}.each { |n| ... }
打印
foo bar quz
为什么?
在for
循环中,variablesn
被定义了一次,然后这个定义被用于所有的迭代。 因此,每个块在循环结束时指代具有quz
值的相同的n
。 错误!
在each
循环中,为每次迭代定义新的variablesn
,例如在variablesn
上方定义三个不同的时间。 因此,每个块都指向一个单独的具有正确值的n
。