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
4

1 回答 1

1

resume无论光纤的状态如何,代码都会调用。

通过调用检查光纤是否可以恢复Fiber#alive?

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

注意你需要做require 'fiber'使用alive?方法。


根据问题编辑更新。

原始代码只产生一次。要无限地迭代,你需要循环。

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
于 2014-01-13T04:17:04.813 回答