可能重复:
Ruby 中的 for vs each
假设我们有一个数组,比如
sites = %w[stackoverflow stackexchange serverfault]
有什么区别
for x in sites do
puts x
end
和
sites.each do |x|
puts x
end
?
对我来说,它们似乎在做同样的事情,for
循环的语法对我来说更清楚。有区别吗?在什么情况下这会很重要?
可能重复:
Ruby 中的 for vs each
假设我们有一个数组,比如
sites = %w[stackoverflow stackexchange serverfault]
有什么区别
for x in sites do
puts x
end
和
sites.each do |x|
puts x
end
?
对我来说,它们似乎在做同样的事情,for
循环的语法对我来说更清楚。有区别吗?在什么情况下这会很重要?
关于作用域有一个细微的差别,但我建议好好理解它,因为它揭示了 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
是惯用的遍历枚举。它还通过减少副作用的机会更好地尊重函数式编程的范式。
sites.each
块内的作用域x
,而如果在块外声明,for
则将重用x
。一般来说,最好使用each
,它可以最大限度地减少对大量代码的副作用。
CBZ 的答案是正确的,但不完整,因为 1.8.X 和 1.9.X 之间的行为有所不同:
1.9.2 内部评级:
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 内部评级法:
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 的答案是正确的。为了说明这一点,请参见以下示例:
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