[ruby] 루비에서 “for”vs “each”

루비의 루프에 관한 간단한 질문이 있습니다. 컬렉션을 반복하는 두 가지 방법 사이에 차이점이 있습니까?

# way 1
@collection.each do |item|
  # do whatever
end

# way 2
for item in @collection
  # do whatever
end

이것들이 정확히 같은지 또는 미묘한 차이가 있는지 궁금합니다 (아마도 @collection0 일 때 ).



답변

이것이 유일한 차이점입니다.

마다:

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루프를 사용하면 블록이 완료된 후에 반복자 변수가 계속 남아 있습니다. each루프를 사용하면 루프가 시작되기 전에 이미 로컬 변수로 정의되지 않은 한 루프가 아닙니다.

그 외에는 메소드의 for구문 설탕 일뿐 each입니다.

@collection입니다 nil모두 루프는 예외를 throw :

예외 : main : Object에 대한 정의되지 않은 지역 변수 또는 메소드`@collection ‘


답변

자세한 설명은 ” For 루프의 악 “을 참조하십시오 (변수 범위 지정을 고려하면 약간의 차이가 있습니다).

사용 each은 Ruby의 관용적 인 사용으로 간주됩니다 .


답변

첫 번째 예

@collection.each do |item|
  # do whatever
end

더 관용적 입니다. Ruby는 forand 같은 루핑 구문을 지원하지만 while일반적으로 블록 구문이 선호됩니다.

또 다른 미묘한 차이점은 for루프 내에서 선언 한 모든 변수는 루프 외부에서 사용할 수있는 반면 반복자 블록 내의 변수 는 사실상 비공개입니다.


답변

하나 더 ..

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


답변

차이가없는 것처럼 보이며 아래를 for사용합니다 each.

$ 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

Bayard가 말했듯이, 각각은 관용적입니다. 더 많은 것을 숨기고 특별한 언어 기능이 필요하지 않습니다.
Telemachus의 의견

for .. in .. 반복자를 루프 범위 밖에서 설정하므로

for a in [1,2]
  puts a
end

a루프가 완료된 후 정의 된 잎 . 어디로 each하지 않습니다. 어떤 사용을 선호하는 또 다른 이유는 each임시 변수가 짧은 기간을 살고 있기 때문에.


답변

절대 사용하지 for않으면 거의 추적 할 수없는 버그가 발생할 수 있습니다.

속지 마십시오. 이것은 관용적 코드 나 스타일 문제에 관한 것이 아닙니다. Ruby의 구현 for에는 심각한 결함이 있으므로 사용해서는 안됩니다.

다음은 for버그를 소개 하는 예입니다.

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}.each { |n| ... }인쇄물 사용

foo
bar
quz

왜?

A의 for루프 변수는 n한번에 단지 한 다음 정의는 모든 반복에 대한 용도가 있음을 정의한다. 따라서 각 블록 은 루프가 종료 될 때까지의 n값을 갖는 블록을 참조합니다 quz. 곤충!

에서 each루프 새로운 변수는 n가변 위의 예를 들어, 각 반복에 대해 정의 된 n별도의 세 번 정의된다. 따라서 각 블록 n은 올바른 값 을 가진 별도 를 참조 합니다.


답변

내가 아는 한, 언어 제어 구조 대신 블록을 사용하는 것이 관용적입니다.