纤维与显式枚举器

时间:2013-09-20 23:17:59

标签: ruby enumerator fibers

我正在玩弄Ruby以学习语言。目前,我正试图围绕纤维的概念。根据{{​​3}},它们经常用于创建(无限)外部枚举器。另一方面,这似乎与所谓的显式枚举器的概念重叠。

说,我想写一个触发连续素数的代码片段(是的,以下算法的运行时为O(可怕))。我可以通过使用光纤来实现它:

prime_fiber = Fiber.new do
    primes = [2]
    Fiber.yield 2
    current = 1
    loop do
        current += 2 
        unless primes.find {|value| (current % value) == 0}
            Fiber.yield current
            primes << current
        end
    end
end

ARGV[0].to_i.times {print "#{prime_fiber.resume}, "}

这不会自己发出枚举器对象,尽管创建一个枚举对象并不困难。相反,我也可以使用一个显式定义的枚举器,它具有已经是枚举器对象的额外好处:

prime_enum = Enumerator.new do |yielder|
    primes = [2]
    yielder.yield 2
    current = 1 
    loop do
        current += 2
        unless primes.find {|value| (current % value) == 0}
            yielder.yield current
            primes << current
        end
    end
end

ARGV[0].to_i.times {print "#{prime_enum.next}, "}
# I could also write:
# p prime_enum.first(ARGV[0].to_i)

这两种方法都允许我实现某种协同例程,它们似乎可以互换。那么我什么时候比较喜欢一个呢?有一些共同商定的做法吗?我觉得很难把所有这些成语都记在脑子里,所以如果这被认为是一个愚蠢的问题,我会提前道歉。

1 个答案:

答案 0 :(得分:1)

我会使用Enumerator,如果您的序列是有限的,它允许您使用taketake_while,甚至each。虽然Fiber是为轻量级并发而设计的,但作为枚举器非常有限。

prime_enum.take(ARGV[0].to_i).each { |x| puts x }

prime_enum.take_while { |x| x < ARGV[0].to_i }.each { |x| puts x }