Ruby';的枚举器对象在内部迭代器上进行外部迭代?

Ruby';的枚举器对象在内部迭代器上进行外部迭代?,ruby,iterator,enumerator,Ruby,Iterator,Enumerator,根据Ruby的文档,如果没有为to_enum或enum\u for方法提供目标方法,枚举器对象将使用each方法(枚举)。现在,让我们以下面的monkey patch及其枚举器为例 o = Object.new def o.each yield 1 yield 2 yield 3 end e = o.to_enum loop do puts e.next end 假设枚举器对象在调用next时使用each方法进行应答,那么每次调用next时,对each方法的调用是

根据Ruby的文档,如果没有为
to_enum
enum\u for
方法提供目标方法,枚举器对象将使用
each
方法(枚举)。现在,让我们以下面的monkey patch及其枚举器为例

o = Object.new
def o.each
    yield 1
    yield 2
    yield 3
end
e = o.to_enum

loop do
  puts e.next
end
假设枚举器对象在调用
next
时使用
each
方法进行应答,那么每次调用
next
时,对
each
方法的调用是什么样子的?Enumeartor类是否预加载
o.each
的所有内容并为枚举创建本地副本?或者是否存在某种Ruby魔法,将每个yield语句的操作挂起,直到在枚举器上调用
next

如果制作了内部拷贝,它是深度拷贝吗?那么可以用于外部枚举的I/O对象呢


我使用的是Ruby 1.9.2。

它并不是那么神奇,但它仍然很漂亮。不是制作某种类型的副本,而是首先在目标可枚举对象上执行
每个
。在接收到每个的下一个对象后,
光纤
产生该对象,从而将控制权返回到最初恢复光纤的位置

它很漂亮,因为这种方法不需要可枚举对象的副本或其他形式的“备份”,例如,可以想象通过调用
#来获取可枚举对象的
。使用光纤的协作调度允许在需要时准确切换上下文,而无需保持某种形式的前瞻性

这一切都发生在for
枚举器中。显示大致相同行为的纯Ruby版本可能如下所示:

class MyEnumerator
  def initialize(enumerable)
    @fiber = Fiber.new do
      enumerable.each { |item| Fiber.yield item }
    end
  end

  def next
    @fiber.resume || raise(StopIteration.new("iteration reached an end"))
  end
end

class MyEnumerable
  def each
    yield 1
    yield 2
    yield 3
  end
end

e = MyEnumerator.new(MyEnumerable.new)
puts e.next # => 1
puts e.next # => 2
puts e.next # => 3
puts e.next # => StopIteration is raised

正如您所知,您可以在文本周围使用倒勾(`)来进行内联代码格式化
:)
muchas gracias!下次我会记住的。太好了!我将更详细地阅读光纤,但是这些绿色线程是由语言创建的,用于将控制权返回给调用者吗?换句话说,控制是如何返回的?@SalmanParacha在解释差异方面比我做得更好。如果您想了解这些血淋淋的细节,那么实现就在@SalmanParacha:Fibers是Ruby对协同路由的名称。协同例程是子例程的泛化:子例程总是从一开始就开始运行,并且总是返回给调用者。协同程序从上次停止的点开始运行,它可以“返回”(或更准确地说,转移控制)到任何其他协同程序,而不仅仅是它来自的那个。@Casper:我想我知道你的意思:)实现对一个项目有一个有效的“前瞻”。@emboss Yes..对。抱歉,我删除了评论。我意识到我只在ruby 1.8本机实现上测试了它,而实际上还没有在ruby 1.9和Fiber上测试过它。但我认为在那里也是一样的。