【问题标题】:Fibers vs. explicit enumerators纤维与显式枚举器
【发布时间】:2013-09-20 23:17:59
【问题描述】:

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

说,我想编写一个触发连续素数的代码 sn-p(是的,以下算法的运行时间为 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)

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

【问题讨论】:

    标签: ruby enumerator fibers


    【解决方案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 }
    

    【讨论】:

    • 所以,我想只要只需要 sequences 值就推荐使用枚举器,并且如果我想强调代码的并发方面,我应该使用纤程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-17
    • 2012-09-16
    • 2012-06-08
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多