views:

97

answers:

5

I just had a quick question regarding loops in Ruby. Is there a difference between these two ways of iterating through a collection?

# way 1
@collection.each do |item|
  # do whatever
end

# way 2
for item in @collection
  # do whatever
end

Just wondering if these are exactly the same or if maybe there's a subtle difference (possibly when @collection is nil). Thanks in advance

+2  A: 

Your first example,

@collection.each do |item|
  # do whatever
end

is more idiomatic. While ruby supports looping constructs like for and while, the block syntax is generally preferred.

Another subtle difference is that any variable you declare within a for loop will be available outside the loop, where as those within an iterator block are effectively private.

Bayard Randel
A: 

As far as I know, using blocks instead of in-language control structures is more idiomatic.

Jonathan Sterling
+1  A: 

It looks like there is no difference, for uses each underneath.

$ 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

Like Bayard says, each is more idiomatic. It hides more from you and doesn't require special language features. Per Telemachus's Comment

for .. in .. sets the iterator outside the scope of the loop, so

for a in [1,2]
  puts a
end

leaves a defined after the loop is finished. Where as each doesn't. Which is another reason in favor of using each, because the temp variable lives a shorter period.

BaroqueBobcat
There _is_ a small difference (as yjerem, ChristopheD and Bayard mention) concerning variable scope.
Telemachus
+3  A: 

See this link for a good explanation (there's one small difference considering variable scoping).

Using each is considered more idiomatic use of Ruby.

ChristopheD
+1 This link is incredibly interesting.
fd
+6  A: 

This is the only difference:

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

With the for loop, the iterator variable still lives after the block is done. With the each loop, it doesn't, unless it was already defined as a local variable before the loop started.

Other than that, for is just syntax sugar for the each method.

yjerem