How do I implement a basic Enumerator class?
I am trying to understand how Enumerator class works. Specifically, I do not know how the yielder object is created and passed to the code block that the constructor takes.
Here is my first try:
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 }
It is not working, of course because I do not know how to advance the enumerator. Could somebody help me in understanding how I can implement it?
You should use some mechanism of continuation. Check:
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
Also, it should be pretty trivial to implement enumerators with fibers (but maybe they are too "high-level" if you want to understand the whole thing, try with continuations then):
http://www.ruby-doc.org/core-1.9.2/Fiber.html
Here's one way to build a basic enumerator (updated with tokland's suggestion):
class MyEnumerator
def initialize
@fiber = Fiber.new { yield Fiber }
end
def next
@fiber.resume
end
end
Usage:
>> 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
精彩评论