Ruby';的枚举器对象在内部迭代器上进行外部迭代?
根据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方法的调用是
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上测试过它。但我认为在那里也是一样的。