-
Notifications
You must be signed in to change notification settings - Fork 608
/
enumerator18.rb
49 lines (43 loc) · 1.35 KB
/
enumerator18.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# -*- encoding: us-ascii -*-
module Enumerable
class Enumerator
# Returns the next object in the enumerator
# and move the internal position forward.
# When the position reached at the end,
# internal position is rewound then StopIteration is raised.
#
# Note that enumeration sequence by next method
# does not affect other non-external enumeration methods,
# unless underlying iteration methods itself has side-effect, e.g. IO#each_line.
#
def next
unless @generator
# Allow #to_generator to return nil, indicating it has none for
# this method.
if @object.respond_to? :to_generator
@generator = @object.to_generator(@iter)
end
if !@generator and gen = FiberGenerator
@generator = gen.new(self)
else
@generator = ThreadGenerator.new(self, @object, @iter, @args)
end
end
begin
return @generator.next if @generator.next?
rescue StopIteration
end
@generator.rewind
raise StopIteration, "iteration reached end"
end
# Rewinds the enumeration sequence by the next method.
#
# If the enclosed object responds to a "rewind" method, it is called.
#
def rewind
@object.rewind if @object.respond_to? :rewind
@generator.rewind if @generator
self
end
end
end