我有一个关于Ruby循环的问题。这两种遍历集合的方法有区别吗?
# way 1
@collection.each do |item|
# do whatever
end
# way 2
for item in @collection
# do whatever
end
只是想知道这些是否完全相同,或者是否可能有细微的差异(可能在@collection为nil时)。
我有一个关于Ruby循环的问题。这两种遍历集合的方法有区别吗?
# way 1
@collection.each do |item|
# do whatever
end
# way 2
for item in @collection
# do whatever
end
只是想知道这些是否完全相同,或者是否可能有细微的差异(可能在@collection为nil时)。
当前回答
看起来没有什么区别,因为它们都在下面使用。
$ 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
就像贝亚德说的,每一个都更习惯。它对您隐藏了更多,并且不需要特殊的语言功能。 根据Telemachus的评论
为. .在. .将迭代器设置在循环范围之外,因此
for a in [1,2]
puts a
end
循环结束后留下一个已定义的对象。而每个人都没有。这是支持使用each的另一个原因,因为临时变量存在的时间较短。
其他回答
第一个例子,
@collection.each do |item|
# do whatever
end
更习惯用语。虽然Ruby支持for和While等循环结构,但块语法通常是首选。
另一个微妙的区别是,在for循环中声明的任何变量在循环之外都是可用的,而迭代器块中的变量实际上是私有的。
这是唯一的区别:
每一个:
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
对于for循环,迭代器变量在块完成后仍然存在。对于每个循环,它都不会,除非它在循环开始之前已经定义为局部变量。
除此之外,for只是每个方法的语法糖。
当@collection为nil时,两个循环都会抛出异常:
异常:main:Object未定义的局部变量或方法“@collection”
永远不要使用,因为它可能会导致几乎不可追踪的bug。
不要被愚弄了,这不是关于惯用代码或风格的问题。Ruby的for实现有一个严重的缺陷,不应该使用。
下面是一个for引入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
打印
quz
quz
quz
使用%w{foo bar quz}。每个{|n|…}打印
foo
bar
quz
Why?
在for循环中,变量n定义一次且仅一次,然后该定义将用于所有迭代。因此,在循环结束时,每个块都指向相同的n,其值为quz。错误!
在每个循环中,每次迭代都定义一个新的变量n,例如上面的变量n定义了三次。因此,每个块都指向一个单独的具有正确值的n。
还有一个不同的…
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
来源:http://paulphilippov.com/articles/enumerable-each-vs-for-loops-in-ruby
想要更清楚:http://www.ruby-forum.com/topic/179264#784884
据我所知,使用块而不是语言内的控制结构更习惯。