Ruby &引用;至于;vs";每一个;红宝石色
我刚才问了一个关于Ruby中循环的快速问题。这两种迭代集合的方法有区别吗Ruby &引用;至于;vs";每一个;红宝石色,ruby,loops,foreach,iteration,each,Ruby,Loops,Foreach,Iteration,Each,我刚才问了一个关于Ruby中循环的快速问题。这两种迭代集合的方法有区别吗 # way 1 @collection.each do |item| # do whatever end # way 2 for item in @collection # do whatever end 只是想知道它们是否完全相同,或者是否存在细微差异(可能是在@collection为零时)。您的第一个示例 @collection.each do |item| # do whatever end 。虽然
# way 1
@collection.each do |item|
# do whatever
end
# way 2
for item in @collection
# do whatever
end
只是想知道它们是否完全相同,或者是否存在细微差异(可能是在@collection
为零时)。您的第一个示例
@collection.each do |item|
# do whatever
end
。虽然Ruby支持循环结构,如for
和While
,但块语法通常是首选的
另一个细微的区别是,在
for
循环中声明的任何变量都将在循环外可用,而迭代器块中的变量实际上是私有的。据我所知,使用块而不是在语言控制结构中更为惯用。看起来没有区别,for
使用下面的每个
$ 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的评论
用于。。in.
将迭代器设置在循环范围之外,因此
for a in [1,2]
puts a
end
在循环完成后留下定义的a
。其中as每个
都没有。这是支持使用每个的另一个原因,因为temp变量的寿命较短。请参阅“”,以获得更好的解释(考虑变量范围有一个小差异)
使用每个都使用Ruby。这是唯一的区别:
每个:
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
irb> for x in [1,2,3]; end
=> [1, 2, 3]
irb> x
=> 3
用于:
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
irb> for x in [1,2,3]; end
=> [1, 2, 3]
irb> x
=> 3
使用for
循环,迭代器变量在块完成后仍然有效。对于每个
循环,它不会,除非它在循环开始之前已经定义为局部变量
除此之外,for
只是每个方法的语法糖
当@collection
为nil
时,两个循环都会引发异常:
异常:main:Object的未定义局部变量或方法“@collection”
还有一个不同的
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
number=[“一”、“二”、“三”]
=>[“一”、“二”、“三”]
loop1=[]
loop2=[]
编号:每个do | c|
循环1[“一”、“二”、“三”]
对于c的数字
循环2[“一”、“二”、“三”]
loop1[1]。调用
二
=>零
loop2[1]。调用
三
=>零
资料来源:
更清楚地说:永远不要使用for
它可能会导致几乎无法追踪的错误
不要被愚弄了,这与惯用代码或样式问题无关。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
使用%w{foo-bar-quz}。每个{n |…}
打印
foo
bar
quz
为什么?
在for
循环中,变量n
只定义一次,然后一个定义用于所有迭代。因此,在循环结束时,每个块都引用相同的n
,其值为quz
。臭虫
在每个
循环中,为每个迭代定义一个新变量n
,例如,在上面,变量n
被定义三次。因此,每个块都使用正确的值引用一个单独的n
我只想就Ruby中的for-in循环提出一个具体的观点。它看起来像是一个类似于其他语言的构造,但实际上它是一个类似于Ruby中其他循环构造的表达式。事实上,for和each迭代器一样使用可枚举对象
传递给for in的集合可以是具有each迭代器方法的任何对象。数组和散列定义了每个方法,许多其他Ruby对象也定义了。for/in循环调用指定对象的each方法。当迭代器生成值时,for循环将每个值(或每组值)分配给指定的变量(或多个变量),然后执行主体中的代码
这是一个愚蠢的示例,但说明了for in循环与任何具有each方法的对象一起工作的要点,就像each迭代器所做的那样:
class Apple
TYPES = %w(red green yellow)
def each
yield TYPES.pop until TYPES.empty?
end
end
a = Apple.new
for i in a do
puts i
end
yellow
green
red
=> nil
现在是每个迭代器:
a = Apple.new
a.each do |i|
puts i
end
yellow
green
red
=> nil
正如您所看到的,这两种方法都响应于each方法,从而将值返回到块。正如这里的每个人所说的,在for-in循环中使用each迭代器是绝对可取的。我只是想让大家明白,for-in循环没有什么神奇之处。它是一个表达式,调用集合的每个方法,然后将其传递给其代码块。因此,这是一种非常罕见的情况,您需要在中使用它。几乎总是使用each迭代器(增加了块范围的好处)
在“for”循环中,局部变量在每个循环后仍然有效。在“each”循环中,局部变量在每个循环后刷新 关于变量范围有一个小的区别(如yjerem、ChristopheD和Bayard所提到的)。不正确,for
不使用下面的每个。请参阅其他答案。@akuhn如需进一步澄清,请参阅此答案及其两个优秀答案。@zachlatta:谢谢通知。我将编辑链接,指向文章的webarchive.org变体!是新的链接,现在JEG2的网站又重新上线了。有没有一个好的理由让x留在for的案例中,或者这是一个糟糕的设计:P?在我看来,与大多数其他语言相比,这似乎是不直观的。@cyc115x
之所以保留在for场景中,是因为(一般来说)关键字不会创建新的作用域。如果、除非、开始、for、while等都在当前范围内工作<代码>#但每个
都接受一个块。块总是在当前作用域的顶部添加它们自己的作用域。这意味着在块中声明一个新变量(因此是一个新范围)将无法从块外访问,因为该附加范围在块外不可用。而
和
直到
实际上有一些非常具体的用途,无法使用