2012-06-15 5 views
5

to_enum 또는 enum_for 메서드에 대상 메서드가 제공되지 않으면 루머의 설명서에 따라 열거 자 개체에 each 메서드가 사용됩니다 (열거하도록). 이제Ruby의 Enumerator 객체는 내부 반복자를 통해 외부에서 반복 처리됩니다.

o = Object.new 
def o.each 
    yield 1 
    yield 2 
    yield 3 
end 
e = o.to_enum 

loop do 
    puts e.next 
end 

열거 객체가 같은 each 방법 모양에 대한 호출을 어떻게, next가 호출 될 때 응답하도록 each 방법을 사용하는 점을 감안 할 때마다의가 예를 들어, 다음 원숭이 패치와 열거 보자 next이 호출됩니까? Enumeartor 클래스가 o.each의 모든 내용을 미리로드하고 열거 용 로컬 복사본을 만드나요? 또는 enumeartor에 next이 호출 될 때까지 각 산출량 명세서에서 연산을 정지시키는 일종의 Ruby 매직이 있습니까?

내부 복사본이 만들어지면 딥 복사본입니까? 외부 열거에 사용할 수있는 I/O 객체는 어떻습니까?

저는 Ruby 1.9.2를 사용하고 있습니다.

+2

를, 당신은 '인라인 코드 포맷을 텍스트 주변에 역 따옴표 (\를') 사용)' –

+0

muchas 그라시아을! 다음 번에는 그 점을 명심하십시오. –

답변

8

정확하게 마법은 아니지만 그럼에도 불구하고 아름답습니다. 일종의 복사본을 만드는 대신 Fiber을 사용하여 대상 열거 가능 객체에서 each을 먼저 실행합니다. each의 다음 개체를받은 후 Fiber이이 개체를 생성하므로 제어가 처음에 Fiber이 다시 시작된 위치로 돌아갑니다.

이 방법은 예를 들어 #to_a을 열거 형에서 호출하여 얻을 수 있다고 생각할 수 있으므로 열거 형 개체의 복사본이나 다른 형태의 "백업"이 필요 없기 때문에 아름답습니다. 광섬유와의 협업 스케줄링은 미리보기의 일부 형식을 유지할 필요없이 필요한 경우 컨텍스트를 정확하게 전환 할 수 있습니다.

모두 C codeEnumerator에 발생합니다. 거의 같은 동작을 보여줄 것입니다 순수 루비 버전은 다음과 같을 수 있습니다 : 당신이 그냥 알다시피

class MyEnumerator 
    def initialize(enumerable) 
    @fiber = Fiber.new do 
     enumerable.each { |item| Fiber.yield item } 
    end 
    end 

    def next 
    @fiber.resume || raise(StopIteration.new("iteration reached an end")) 
    end 
end 

class MyEnumerable 
    def each 
    yield 1 
    yield 2 
    yield 3 
    end 
end 

e = MyEnumerator.new(MyEnumerable.new) 
puts e.next # => 1 
puts e.next # => 2 
puts e.next # => 3 
puts e.next # => StopIteration is raised 
+0

니스! 섬유에 대해 좀 더 자세하게 설명 하겠지만 호출자에게 제어권을 반환하기 위해 언어에 의해 만들어진 이러한 녹색 스레드입니까? 다시 말해, 컨트롤은 어떻게 반환됩니까? –

+0

@SalmanParacha [위키 피 디아] (http://en.wikipedia.org/wiki/Fiber_ (computer_science))는 내가 할 수있는 것보다 더 나은 차이를 설명합니다. 자세한 내용을 원하면 구현은 [cont.c] (https://github.com/ruby/ruby/blob/trunk/cont.c)에 있습니다. – emboss

+1

@SalmanParacha : 섬유는 루틴의 coroutines의 이름입니다. 코 루틴 (coroutine)은 서브 루틴의 일반화입니다. 서브 루틴 *은 항상 처음부터 실행되기 시작하며 항상 호출자에게 되돌아갑니다. 코 루틴 (coroutine)은 마지막으로 중지 된 지점에서 실행되며 해당 코 루틴이 출현 한 코 루틴이 아닌 다른 모든 코 루틴으로 "반환"(또는보다 정확하게 전달 제어) 할 수 있습니다. –

관련 문제