挖这一点,这里是一个很酷的Enumerator
(懒惰序列)从1到(最大Float
红宝石可以代表):为什么枚举包括可枚举
1.9.3-p327 :014 > e = (1..Float::INFINITY).each
看看我们如何能抓住序列的前:
1.9.3-p327 :015 > e.first
=> 1
1.9.3-p327 :016 > e.take(2)
=> [1, 2]
这是好东西吧?我也这么认为。但那么这个:
1.9.3-p327 :017 > e.drop(2).first
进入lala土地。我的意思是,它不会在不到5秒的时间内返回。这里
哦,是一个线索:
1.9.3-p327 :020 > p e.method(:drop)
#<Method: Enumerator(Enumerable)#drop>
看来,枚举(e
)得到它从Enumerable
(模块)#drop
方法到Enumerator
(类)混合。现在为什么在世界上Ruby会去Enumerable
到Enumerator
你问?我不知道。但在那里,记录在Enumerator
in Ruby 1.9.3和Enumerator
in Ruby 2.0。
我看到的问题是Enumerable
中定义的一些方法在Enumerator
上的工作或种类。示例包括#first
和#take
。至少有一个:#drop
不起作用。
在我看来,Enumerator
包括Enumerable
是一个错误。你怎么看?请注意,Ruby 2.0定义了Enumerator::Lazy
(Enumerator
的子类),它定义了一堆非常懒惰的Enumerable
方法。有东西在这里闻起来有些腥臭。为什么混入非懒惰的方法和某些情况下破坏的方法(到Enumerator
)只能在子类中(Enumerator
)转向并提供懒惰的替代方法?
参见:
1.9.3-p327 :018 > p e.method(:first)
#<Method: Enumerator(Enumerable)#first>
1.9.3-p327 :020 > p e.method(:drop)
#<Method: Enumerator(Enumerable)#drop>
请注意,'e =(1..Float :: INFINITY).each'中的'each'没有区别。你应该放弃它,或者用“懒惰”来取代它,这取决于你想要的东西。 – 2013-04-11 01:14:52
谢谢Marc-André。但是Ruby 1.9.3中没有Enumerable#懒。这仅在2.0版本中可用。我认为我的一个主要误解是假设#drop完全返回了一个Enumerator。出于某种原因,虽然#drop和#take都有可能的微不足道的枚举器实现,但它们都不会返回枚举器!即使修复了[Ruby Bug#7715“懒惰枚举员应该保持懒惰”](https://bugs.ruby-lang.org/issues/7715)也无法解决这些问题。想想看,这些不能“固定”,因为这样做会破坏依赖于返回数组的代码! – 2013-04-11 04:52:55
的确,“drop”是“渴望”的。顺便说一句,你可以在'require'backports/2.0.0/enumerable/lazy''的任何版本的Ruby中使用'lazy'' – 2013-04-11 06:42:39