Вопрос

I am toying around with Ruby to learn the language. Currently I'm trying to wrap my head around the concept of fibers. According to this answer, they are fairly often used for creating (infinite) external enumerators. On the other hand, this seems to overlap with the concept of so called explicit enumerators.

Say, I want to write a code snippet that fires consecutive prime numbers (yes, the following algorithm has a runtime of O(scary)). I can implement it by using fibers:

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}, "}

This does not emit an enumerator object by itself, although it is not difficult to create one out of it. In contrast, I can also utilize an explicitly defined enumerator, which has the added benefit of already being an enumerator object:

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)

Both methods allow me to implement some sort of co-routines and they seem to be interchangeable to me. So when do I prefer one over the other? Is there some commonly agreed practice? I find it difficult to get all those idioms in my head, so I apologize in advance if this is considered a dumb question.

Это было полезно?

Решение

I would use Enumerator, it allows you to use take, take_while, even each if your sequence is finite. While Fiber is designed for light weight concurrency and is pretty limited as enumerator.

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

or

prime_enum.take_while { |x| x < ARGV[0].to_i }.each { |x| puts x }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top