Possible Duplicate:
for vs each in Ruby
Let's say that we have an array, like
sites = %w[stackoverflow stackexchange serverfault]
What's the difference between
for x in sites do
puts x
end
and
sites.each do |x|
puts x
end
?
They seem to do the same exact thing, to me, and the syntax of the for
loop is clearer to me. Is there a difference? In what situations would this be a big deal?
There is a subtle difference regarding scoping, but I would recommend understanding it well as it reveals some of important aspects of Ruby.
for
is a syntax construct, somewhat similar to if
. Whatever you define in for
block, will remain defined after for
as well:
sites = %w[stackoverflow stackexchange serverfault]
#=> ["stackoverflow", "stackexchange", "serverfault"]
for x in sites do
puts x
end
stackoverflow
stackexchange
serverfault
#=> ["stackoverflow", "stackexchange", "serverfault"]
x
#=> "serverfault"
On the other hand, each
is a method which receives a block. Block introduces new lexical scope, so whatever variable you introduce in it, will not be there after the method finishes:
sites.each do |y|
puts y
end
stackoverflow
stackexchange
serverfault
#=> ["stackoverflow", "stackexchange", "serverfault"]
y
NameError: undefined local variable or method `y' for #<Object:0x855f28 @hhh="hello">
from (irb):9
from /usr/bin/irb:12:in `<main>'
I would recommend forgetting about for
completely, as using each
is idiomatic in Ruby for traversing enumerables. It also recspects the paradigm of functional programming better, by decreasing chances of side-effects.
sites.each
scopes x
inside the block, whereas for
will reuse x
if declared outside the block. In general it's better therefore to use each
, it minimizes side effects over large bodies of code.
CBZ answer is correct but incomplete since there is a difference in behavior between 1.8.X and 1.9.X:
1.9.2 IRB:
ruby-1.9.2-p180 :001 > x = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
ruby-1.9.2-p180 :002 > y = ["a","b"]
=> ["a", "b"]
ruby-1.9.2-p180 :003 > x.each do |y|
ruby-1.9.2-p180 :004 > p y
ruby-1.9.2-p180 :005?> end
1
2
3
4
5
=> [1, 2, 3, 4, 5]
ruby-1.9.2-p180 :006 > y
=> ["a", "b"]
1.8.7 IRB:
ree-1.8.7-2011.03 :001 > x = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
ree-1.8.7-2011.03 :002 > y = ["a","b"]
=> ["a", "b"]
ree-1.8.7-2011.03 :003 > x.each do |y|
ree-1.8.7-2011.03 :004 > p y
ree-1.8.7-2011.03 :005?> end
1
2
3
4
5
=> [1, 2, 3, 4, 5]
ree-1.8.7-2011.03 :006 > y
=> 5
CBZ answer is correct. To illustrate this, see this example:
ruby-1.9.2-p180 :001 > a = %w{ blah lah kah }
=> ["blah", "lah", "kah"]
ruby-1.9.2-p180 :002 > x = 1
=> 1
ruby-1.9.2-p180 :003 > for x in a do
ruby-1.9.2-p180 :004 > puts x
ruby-1.9.2-p180 :005?> end
blah
lah
kah
=> ["blah", "lah", "kah"]
ruby-1.9.2-p180 :006 > x
=> "kah"
ruby-1.9.2-p180 :007 > x=1
=> 1
ruby-1.9.2-p180 :008 > a.each do |x|
ruby-1.9.2-p180 :009 > puts x
ruby-1.9.2-p180 :010?> end
blah
lah
kah
=> ["blah", "lah", "kah"]
ruby-1.9.2-p180 :011 > x
=> 1
来源:https://stackoverflow.com/questions/5677081/ruby-what-is-the-difference-between-a-for-loop-and-an-each-loop