Ruby:for 循环和each 循环有什么区别?

发布于 2024-11-02 02:33:59 字数 489 浏览 0 评论 0原文

可能的重复:
Ruby 中的 for 与 every

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

sites = %w[stackoverflow stackexchange serverfault]

之间有什么区别

for x in sites do
  puts x
end

sites.each do |x|
  puts x
end

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

楠木可依 2024-11-09 02:33:59

关于作用域有一个微妙的差异,但我建议充分理解它,因为它揭示了 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 ,因为使用 each 是惯用的在 Ruby 中用于遍历枚举。它还通过减少副作用的机会来更好地尊重函数式编程的范式。

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.

忘你却要生生世世 2024-11-09 02:33:59

sites.each 作用域 x 位于块内,而 for 如果在块外部声明,则将重用 x。一般来说,最好使用each,它可以最大限度地减少大型代码体的副作用。

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.

夏了南城 2024-11-09 02:33:59

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 

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 
丑疤怪 2024-11-09 02:33:59

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 

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 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文