mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
66211394e1
### Example:
```ruby
# example.rb
e = [1]
def e.rewind; p :r end
c = e.chain(e)
c.each{break c}.rewind
```
#### Before this patch:
```terminal
$ bin/mruby example.rb
:r
:r
```
#### After this patch (same as Ruby):
```terminal
$ bin/mruby example.rb
:r
```
63 lines
977 B
Ruby
63 lines
977 B
Ruby
##
|
|
# chain.rb Enumerator::Chain class
|
|
# See Copyright Notice in mruby.h
|
|
|
|
module Enumerable
|
|
def chain(*args)
|
|
Enumerator::Chain.new(self, *args)
|
|
end
|
|
end
|
|
|
|
class Enumerator
|
|
def +(other)
|
|
Chain.new(self, other)
|
|
end
|
|
|
|
class Chain
|
|
include Enumerable
|
|
|
|
def initialize(*args)
|
|
@enums = args.freeze
|
|
@pos = -1
|
|
end
|
|
|
|
def each(&block)
|
|
return to_enum unless block
|
|
|
|
i = 0
|
|
while i < @enums.size
|
|
@pos = i
|
|
@enums[i].each(&block)
|
|
i += 1
|
|
end
|
|
|
|
self
|
|
end
|
|
|
|
def size
|
|
@enums.reduce(0) do |a, e|
|
|
return nil unless e.respond_to?(:size)
|
|
a + e.size
|
|
end
|
|
end
|
|
|
|
def rewind
|
|
while 0 <= @pos && @pos < @enums.size
|
|
e = @enums[@pos]
|
|
e.rewind if e.respond_to?(:rewind)
|
|
@pos -= 1
|
|
end
|
|
|
|
self
|
|
end
|
|
|
|
def +(other)
|
|
self.class.new(self, other)
|
|
end
|
|
|
|
def inspect
|
|
"#<#{self.class}: #{@enums.inspect}>"
|
|
end
|
|
end
|
|
end
|