I'm surprised that Enumerator#each doesn't start off at the current position in the sequence.
o = Object.new
def o.each
yield 1
yield 2
yield 3
end
e = o.to_enum
puts e.next
puts e.next
e.each{|x| puts x}
# I expect to see 1,2,3 but I see 1,2,1,2,3
# apparently Enumerator's each (inherited from Enumerable) restarts the sequence!
Am I doin' it wrong? Is there a way to maybe construct another Enumerator (from e) that will have the expected each behavior?
You're not doing it wrong, that's just not the semantics defined for Enumerator#each
. You could make a derivative enumerator that only iterates from current position to end:
class Enumerator
def enum_the_rest
Enumerator.new { |y| loop { y << self.next } }
end
end
o = Object.new
def o.each
yield 1
yield 2
yield 3
end
e = o.to_enum
=> #<Enumerator: ...>
e.next
=> 1
e2 = e.enum_the_rest
=> #<Enumerator: ...>
e2.each { |x| puts x }
=> 2
=> 3
And, BTW, each
doesn't restart the sequence, it just always runs over the entire span. Your enumerator still knows where it is in relation to the next next
call.
e3 = o.to_enum
e3.next
=> 1
e3.next
=> 2
e3.map(&:to_s)
=> ["1", "2", "3"]
e3.next
=> 3