2014-05-21 4 views
5

나는 Enumerator.new 방법이 어떻게 작동하는지 이해하는 데 어려움을 겪고 있습니다. 이 문서에서 예제를 가정 : 블록에서 Enumerator.new가 어떻게 작동합니까?

fib = Enumerator.new do |y| 
    a = b = 1 
    loop do 
    y << a 
    a, b = b, a + b 
    end 
end 

p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] 

어디 루프 브레이크 조건이 어떻게 (이 명시 휴식 조건을 가지고 무한 루프처럼 보이는하지 않는 한) 반복 횟수를 루프 알고 않는거야?

답변

4

Enumerator은 내부적으로 Fibers을 사용합니다. 귀하의 예는 다음과 같습니다 :

require 'fiber' 

fiber = Fiber.new do 
    a = b = 1 
    loop do 
    Fiber.yield a 
    a, b = b, a + b 
    end 
end 

10.times.map { fiber.resume } 
#=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] 
+0

매우 흥미 롭습니다! –

4

편집 지금 질문을 이해합니다.

y << ay.yield(a)의 별명이며 기본적으로는 반환 값이 sleep입니다. 숫자가 next으로 열거 자에서 요청 될 때마다 다른 값이 산출 될 때까지 실행이 계속됩니다.


열거 자 요소의 유한 수를 열거 할 필요가 없습니다, 그래서 그들은 무한이다. 예를 들어, fib.to_a은 무한 개수의 요소가있는 배열을 작성하려고하기 때문에 절대로 종료되지 않습니다.

이와 같이 열거자는 자연수 또는 사용자의 경우 피보나치 수와 같은 무한 시리즈의 표현으로 유용합니다. 열거 자의 사용자는 필요한 값의 수를 결정할 수 있습니다. 예를 들어 take(10)은 사용자가 원하는 경우 중단 조건을 결정합니다.

중단 조건 자체는 구현시 Enumerator#take입니다. 데모 목적을 위해, 우리는 우리 자신의 구현이 my_take라고 할 수 있습니다 :

class Enumerator 
    def my_take(n) 
    result = [] 
    n.times do 
     result << self.next 
    end 
    result 
    end 
end 

어디 당신의 고전적인 C 스타일 for (i=0; i<n; i++)와 "물론 정신적으로 대체"당신의 n.times 루프 수 있습니다. 휴식 조건이 있습니다. 당신은 물론 값의 유한 수를 열거하는 열거를 구축 할 수

말했다
fib.next 
#=> 1 
fib.next 
#=> 1 
fib.next 
#=> 2 
fib.next 
#=> 3 

, 같은 : self.next 당신은 또한 클래스의 외부에서 사용할 수있는 열거의 다음 값을 얻을 수있는 방법이다 주어진 범위의 자연수입니다.하지만 여기서는 그렇지 않습니다. 그런 다음 next을 호출하려고하면 열거자는 StopIteration 오류를 발생 시키지만 모든 값은 이미 열거되었습니다. 이 경우 두 가지 조건이 있습니다. 그러면 이전에 깨지던 것이 승리 할 것입니다. take 실제로 오류에서 구출하여 그 처리, 그래서 다음 코드는 조금 더 실제 구현 (그러나, take 실제로 C에서 구현)입니다.

class Enumerator 
    def my_take(n) 
    result = [] 
    n.times do 
     result << self.next 
    end 
    result 
    rescue StopIteration 
    # enumerator stopped early 
    result 
    end 
end 
+0

멋지지만 루프를 어기는 문장은 어디에 있습니까? '<<'? –

+0

@LeszekAndrukanis 내 편집을 참조하십시오. 열거자는 실제로 무한하며 열거 자에 중단 조건이 없습니다. 원하는 가치의 수를 결정하는 것은 가치의 소비자에게 달려 있습니다! –

+0

@ p11y 나는 각 반복 후에 루비가 무한 루프를 막을 수있는 방법을 알고 싶다고 생각한다. – Stefan

관련 문제