Playing round with fibers and I know I'm doing something stupid here. But trying to create a simple enumerable type thing based on fibers (it's obviously trivial using Enumerable). When I run the following I get a dead fiber error after it prints out the first couple of iterations. Does anyone know why?
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
output:
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>'
This code on the other hand works completely fine:
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 }
output:
1
1
2
3
5
8
13
The code is calling resume
regardless of state of the fiber.
Check whether fiber can resume by calling Fiber#alive?
def each
while @fiber.alive? do
yield self.next
end
end
NOTE You need to do require 'fiber'
to use alive?
method.
UPDATE accoridng to the question edit.
The original code yields only once. To iterate indefinitely, you need loop.
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