227

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).

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
mportiz08
  • 10,206
  • 12
  • 40
  • 42

9 Answers9

335

This is the only difference:

each:

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

for:

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.

When @collection is nil both loops throw an exception:

Exception: undefined local variable or method `@collection' for main:Object

Paul
  • 25,812
  • 38
  • 124
  • 247
Paige Ruten
  • 172,675
  • 36
  • 177
  • 197
  • 4
    is there a good reason why x remains in the for case or is this bad design :P? Seems to me this is rather unintuitive comparing with most other languages. – cyc115 Jun 12 '18 at 18:00
  • 5
    @cyc115 The reason why `x` remains in the *for* scenario is due to the fact that (generally speaking) keywords don't create new scopes. *if*, *unless*, *begin*, *for*, *while*, etc. all work with the current scope. `#each` however accepts a block. Blocks always add their own scope on top of the current scope. Meaning that declaring a new variable in the block (thus a new scope) will not be accessible from outside the block since that additional scope is not available there. – 3limin4t0r Feb 07 '19 at 10:21
  • So does it mean `each` is a better option since it release the iterator from memory after the loop. – Zhou Haibo Sep 27 '22 at 05:19
  • @ChuckZHB: The iterator is released (assuming no other references). It's only the last *value* it produced that might stick around. Whether that's a good or bad thing depends on what you want (sometimes it's useful to have the final value after the loop). – ShadowRanger Feb 17 '23 at 15:17
50

See "The Evils of the For Loop" for a good explanation (there's one small difference considering variable scoping).

Using each is considered more idiomatic use of Ruby.

Grilse
  • 3,491
  • 2
  • 28
  • 35
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
  • @zachlatta: Thanks for notifying. I'll edit the link to point to a webarchive.org variant of the article! – ChristopheD Apr 08 '13 at 22:47
  • 1
    http://graysoftinc.com/early-steps/the-evils-of-the-for-loop is the new link, now that JEG2's site is back online. – pnomolos Jun 11 '14 at 23:32
35

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, whereas those within an iterator block are effectively private.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Bayard Randel
  • 9,930
  • 3
  • 42
  • 46
  • `while` and `until` do actually have some very concrete uses that cannot be replaced with each such as for example generating unique values or for REPL's. – max Aug 04 '19 at 16:08
7

One more different..

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 

source: http://paulphilippov.com/articles/enumerable-each-vs-for-loops-in-ruby

for more clear: http://www.ruby-forum.com/topic/179264#784884

Mr. Black
  • 11,692
  • 13
  • 60
  • 85
7

Never ever use for it may cause almost untraceable bugs.

Don't be fooled, this is not about idiomatic code or style issues. Ruby's implementation of for has a serious flaw and should not be used.

Here is an example where for introduces a bug,

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

Prints

quz
quz
quz

Using %w{foo bar quz}.each { |n| ... } prints

foo
bar
quz

Why?

In a for loop the variable n is defined once and only and then that one definition is use for all iterations. Hence each blocks refer to the same n which has a value of quz by the time the loop ends. Bug!

In an each loop a fresh variable n is defined for each iteration, for example above the variable n is defined three separate times. Hence each block refer to a separate n with the correct values.

akuhn
  • 27,477
  • 2
  • 76
  • 91
2

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
  • 10,090
  • 1
  • 31
  • 37
1
(1..4).each { |i| 


  a = 9 if i==3

  puts a 


}
#nil
#nil
#9
#nil

for i in 1..4

  a = 9 if i==3

  puts a

end
#nil
#nil
#9
#9

In 'for' loop, local variable is still lives after each loop. In 'each' loop, local variable refreshes after each loop.

Kelvin Tan
  • 982
  • 1
  • 12
  • 33
0

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

Jonathan Sterling
  • 18,320
  • 12
  • 67
  • 79
0

I just want to make a specific point about the for in loop in Ruby. It might seem like a construct similar to other languages, but in fact it is an expression like every other looping construct in Ruby. In fact, the for in works with Enumerable objects just as the each iterator.

The collection passed to for in can be any object that has an each iterator method. Arrays and hashes define the each method, and many other Ruby objects do, too. The for/in loop calls the each method of the specified object. As that iterator yields values, the for loop assigns each value (or each set of values) to the specified variable (or variables) and then executes the code in body.

This is a silly example, but illustrates the point that the for in loop works with ANY object that has an each method, just like how the each iterator does:

class Apple
  TYPES = %w(red green yellow)
  def each
    yield TYPES.pop until TYPES.empty?
  end
end

a = Apple.new
for i in a do
  puts i
end
yellow
green
red
=> nil

And now the each iterator:

a = Apple.new
a.each do |i|
  puts i
end
yellow
green
red
=> nil

As you can see, both are responding to the each method which yields values back to the block. As everyone here stated, it is definitely preferable to use the each iterator over the for in loop. I just wanted to drive home the point that there is nothing magical about the for in loop. It is an expression that invokes the each method of a collection and then passes it to its block of code. Hence, it is a very rare case you would need to use for in. Use the each iterator almost always (with the added benefit of block scope).

Daniel Viglione
  • 8,014
  • 9
  • 67
  • 101