1

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

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

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)

这两种方法都允许我实现某种协同程序,而且它们对我来说似乎是可以互换的。那么我什么时候更喜欢其中之一呢?有一些普遍认可的做法吗?我觉得很难把所有这些成语都记在心里,所以如果这被认为是一个愚蠢的问题,我提前道歉。

4

1 回答 1

1

我会使用Enumerator, 它允许你使用take, take_while,即使each你的序列是有限的。WhileFiber是为轻量级并发而设计的,并且作为枚举器非常有限。

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 }
于 2013-09-21T00:17:57.163 回答