【问题标题】:How do I implement a basic Enumerator class?如何实现一个基本的 Enumerator 类?
【发布时间】:2011-10-13 15:57:56
【问题描述】:

我试图了解 Enumerator 类的工作原理。具体来说,我不知道yielder对象是如何创建并传递给构造函数所取的代码块的。

这是我的第一次尝试:

class MyEnumerator
  def initialize(&block)
    @block = block
  end 
  def next()
    @block.call self
  end 
  def yield(*args)
    args
  end 
end


num_gen = MyEnumerator.new do |yielder|
  (1..10).each { |num| yielder.yield num }
end

5.times { p num_gen.next }

它不起作用,当然是因为我不知道如何推进枚举器。有人可以帮助我了解如何实现它吗?

【问题讨论】:

    标签: ruby ienumerator


    【解决方案1】:

    你应该使用一些延续的机制。检查:

    http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_continuation.html

    http://ruby-doc.org/docs/ProgrammingRuby/html/ref_m_kernel.html#Kernel.callcc

    另外,用纤维实现枚举器应该很简单(但如果你想了解整个事情,它们可能太“高级”,然后尝试使用延续):

    http://www.ruby-doc.org/core-1.9.2/Fiber.html

    【讨论】:

      【解决方案2】:

      这是构建基本枚举器的一种方法(根据 tokland 的建议进行了更新):

      class MyEnumerator
        def initialize
          @fiber = Fiber.new { yield Fiber }
        end
      
        def next
          @fiber.resume
        end
      end
      

      用法:

      >> num_gen = MyEnumerator.new { |f| (1..10).each { |x| f.yield x } }
      => #<MyEnumerator:0x007fd6ab8f4b28 @fiber=#<Fiber:0x007fd6ab8f4ab0>>
      >> num_gen.next
      => 1
      >> num_gen.next
      => 2
      >> num_gen.next
      => 3
      >> num_gen.next
      => 4
      

      【讨论】:

      • 整洁。也许“@fiber = Fiber.new { yield Fiber }”来模拟 Enumerator 行为?
      • 我之前有点着急,但现在更好了,谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-06
      • 2010-10-14
      • 2023-03-05
      • 1970-01-01
      • 2011-04-15
      相关资源
      最近更新 更多