如何实现基本的Enumerator类?

时间:2022-11-28 09:54:23

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.

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

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?

它当然不起作用,因为我不知道如何推进普查员。有人可以帮助我理解我如何实现它吗?

2 个解决方案

#1


2  

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):

此外,使用光纤实现枚举器应该是非常简单的(但是如果你想了解整个事情,可能它们太“高级”,那么尝试使用continuation):

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

#2


1  

Here's one way to build a basic enumerator (updated with tokland's suggestion):

这是构建基本枚举器的一种方法(使用tokland的建议更新):

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

#1


2  

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):

此外,使用光纤实现枚举器应该是非常简单的(但是如果你想了解整个事情,可能它们太“高级”,那么尝试使用continuation):

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

#2


1  

Here's one way to build a basic enumerator (updated with tokland's suggestion):

这是构建基本枚举器的一种方法(使用tokland的建议更新):

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