2014-01-13 2 views
1

Игра с волокнами, и я знаю, что я делаю что-то глупое здесь. Но пытаюсь создать простую перечислимую вещь типа на основе волокон (это, очевидно, тривиально, используя Enumerable). Когда я запускаю следующее, я получаю сообщение об ошибке «мертвого волокна» после того, как он распечатает первую пару итераций. Кто-нибудь знает, почему?Рубиновое волокно «мертвое волокно под названием»

class SumPow 
    def initialize(a) 
    sum = a 
    pow = a 
    @fiber = Fiber.new do 
     Fiber.yield sum 
     pow = pow * a 
     sum = sum + pow 
    end 
    end 

    def next 
    @fiber.resume 
    end 

    def each 
    loop do 
     yield self.next 
    end 
    end 

end 

sp = SumPow.new(3) 
sp.each do |sum| 
    puts sum 
end 

выход:

3 
12 
tmp/fiber_enum.rb:96:in `resume': dead fiber called (FiberError) 
    from tmp/fiber_enum.rb:96:in `next' 
    from tmp/fiber_enum.rb:101:in `block in each' 
    from tmp/fiber_enum.rb:100:in `loop' 
    from tmp/fiber_enum.rb:100:in `each' 
    from tmp/fiber_enum.rb:108:in `<main>' 

Этот код с другой стороны работает совершенно нормально:

fib = Fiber.new do 
    x, y = 0, 1 
    loop do 
    Fiber.yield y 
    x, y = y, x + y 
    end 
end 
7.times { puts fib.resume } 

выход:

1 
1 
2 
3 
5 
8 
13 

ответ

1

Код вызова resume независимо от состояния из фида э.

Проверить, может ли волокна резюме по телефону Fiber#alive?

def each 
    while @fiber.alive? do 
    yield self.next 
    end 
end 

ПРИМЕЧАНИЕ Вам нужно сделать require 'fiber' использовать alive? метод.


UPDATE accoridng к вопросу редактирования.

Исходный код дает только один раз. Чтобы итератировать бесконечно, вам нужен цикл.

def initialize(a) 
    sum = a 
    pow = a 
    @fiber = Fiber.new do 
    loop do # <------------- 
     Fiber.yield sum 
     pow = pow * a 
     sum = sum + pow 
    end # <----------------- 
    end 
end 
+0

Извините, я должен был быть более ясным, а что, если бы я хотел итерации бесконечно использовать волокно здесь? – rainkinz

+0

@rainkinz, Код в вопросе дает только один раз: 'Fiber.new do ... end'. – falsetru

+0

@rainkinz, я обновил ответ. – falsetru