1

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 }

もちろん、列挙子を進める方法がわからないため、機能していません。誰かが私がそれを実装する方法を理解するのを手伝ってもらえますか?

4

2 に答える 2

2

何らかの継続メカニズムを使用する必要があります。小切手:

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

于 2011-10-13T16:50:49.863 に答える
1

基本的な列挙子を作成する 1 つの方法を次に示します (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
于 2011-10-13T16:55:51.923 に答える