The answer is but a click away: the documentation for Enumerator:
Most [
Enumerator
] methods [but presumably alsoKernel#to_enum
andKernel#enum_for
] have two forms: a block form where the contents are evaluated for each item in the enumeration, and a non-block form which returns a newEnumerator
wrapping the iteration.
It is the second that applies here:
enum = [4, 1, 2, 0].to_enum(:count) # => #<Enumerator: [4, 1, 2, 0]:count>
enum.class # => Enumerator
enum_ewi = enum.each_with_index
# => #<Enumerator: #<Enumerator: [4, 1, 2, 0]:count>:each_with_index>
enum_ewi.class # => Enumerator
enum_ewi.each {|elem, index| elem == index} # => 2
Note in particular irb's return from the third line. It goes on say, "This allows you to chain Enumerators together." and gives map.with_index
as an example.
Why stop here?
enum_ewi == enum_ewi.each.each.each # => true
yet_another = enum_ewi.each_with_index
# => #<Enumerator: #<Enumerator: #<Enumerator: [4, 1, 2, 0]:count>:each_with_index>:each_with_index>
yet_another.each_with_index {|e,i| puts "e = #{e}, i = #{i}"}
e = [4, 0], i = 0
e = [1, 1], i = 1
e = [2, 2], i = 2
e = [0, 3], i = 3
yet_another.each_with_index {|e,i| e.first.first == i} # => 2
(Edit 1: replaced example from docs with one pertinent to the question. Edit 2: added "Why stop here?)