为什么chunk_while返回Enumerator对象
为什么chunk_while
返回一个Enumerator
实例?
这段代码:
array = [0, 1, 2, 3, 4, 5, 7, 8, 9, 15, 16] p array.chunk_while {|i,j| i + 1 == j }
输出这个:
#:each>
我有ruby版ruby 2.3.1p112 (2016-04-26 revision 54768) [x64-mingw32]
。
Enumerable模块中的方法(如chunk_while
)要求接收者是枚举器,即Enumerator类的实例。 因此,如果一个Enumerable
方法(如chunk_while
返回一个枚举器,它可以是另一个Enumerable
方法的接收者(该方法可以是另一个Enumerable
方法的接收者,依此类推)。 这称为方法链 。 这就是为什么你看到许多Enumerable
方法返回一个枚举器,如果没有提供块。
将枚举器作为接收器的方法的链接还可以包括其他模块或类Enumerator
,例如Enumerator #with_index 。
这就是我们可以编写如下表达式的原因。
array.chunk_while {|i,j| i + 1 == j }.map.with_index { |a,i| i.even? ? a.reduce(:+) : 0 } #=> [15, 0, 31]
让我们打破这个。
e0 = array.chunk_while {|i,j| i + 1 == j } #=> #:each> e1 = e0.map #=> # :each>:map> e2 = e1.with_index #=> # :each>:map>:with_index> e2.each { |a,i| i.even? ? a.reduce(:+) : 0 } #=> [15, 0, 31]
检查生成e0
, e1
和e2
的操作的返回值。 e1
和e2
可以被认为是复合枚举器 。
实际上, chunk_while
几乎总是链接到另一个方法,因此它返回一个枚举器是有意义的。
您可能会问,“为什么所有可枚举的方法都需要一个作为枚举器的接收器,考虑到chunk_while
接收器, array
,不是枚举器”? 答案在于,包含Enumerable
模块的每个类都必须有一个返回枚举器的方法。 因此可以写一个
array.each.chunk_while {|i,j| i + 1 == j }.to_a
但Ruby可以省去你的麻烦。 当Ruby看到在数组上调用的方法需要枚举器作为其接收器时,它将为您调用每个Array# 。 所有具有方法的类都是如此。