The each() is an inbuilt method in Ruby iterates over every element in the range. Parameters: The function accepts a block which specifies the way in which the elements are iterated. Return Value: It returns every elements in the range.
each is just another method on an object. That means that if you want to iterate over an array with each , you're calling the each method on that array object. It takes a list as it's first argument and a block as the second argument.
Ruby has Array#unshift to prepend an element to the start of an array and Array#push to append an element to the end of an array. The names of these methods are not very intuitive. Active Support from Rails already has aliases for the unshift and push methods , namely prepend and append.
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
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.
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.
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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With