Ruby:for循环和每个循环之间有什么区别?

时间:2011-04-15 12:57:03

标签: ruby loops syntax foreach flow-control

  

可能重复:
  for vs each in Ruby

假设我们有一个数组,比如

sites = %w[stackoverflow stackexchange serverfault]

之间有什么区别
for x in sites do
  puts x
end

sites.each do |x|
  puts x
end

他们似乎对我做了同样的事情,for循环的语法对我来说更清晰。有区别吗?在什么情况下这将是一个大问题?

4 个答案:

答案 0 :(得分:26)

关于范围界定存在细微差别,但我建议理解它,因为它揭示了Ruby的一些重要方面。

for是一种语法结构,有点类似于if。无论您在for块中定义什么,都将在for之后保持定义:

sites = %w[stackoverflow stackexchange serverfault]
#=> ["stackoverflow", "stackexchange", "serverfault"]

for x in sites do
  puts x
end
stackoverflow
stackexchange
serverfault
#=> ["stackoverflow", "stackexchange", "serverfault"]
x
#=> "serverfault"

另一方面,each方法,它接收一个块。 Block引入了新的词法范围,因此无论你在其中引入什么变量,在方法完成后都不会出现:

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>'

我建议完全忘记for,因为在Ruby中使用each是惯用的,用于遍历可枚举。它还通过减少副作用的机会来更好地重新考虑函数式编程的范例。

答案 1 :(得分:8)

块内的

sites.each范围x,而for如果在块外声明则将重用x。一般来说,最好使用each,它可以最大限度地减少对大量代码的副作用。

答案 2 :(得分:4)

CBZ答案是正确但不完整的,因为1.8.X和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 

答案 3 :(得分:-1)

CBZ的回答是正确的。为了说明这一点,请参阅此示例:

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