Commit 66211394 authored by KOBAYASHI Shuji's avatar KOBAYASHI Shuji

`Enumerator::Chain#rewind` shouldn't rewind elements aren't iterated

### 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
  ```
parent 0ce1878a
......@@ -17,13 +17,19 @@ class Enumerator
include Enumerable
def initialize(*args)
@enums = args
@enums = args.freeze
@pos = -1
end
def each(&block)
return to_enum unless block_given?
return to_enum unless block
@enums.each { |e| e.each(&block) }
i = 0
while i < @enums.size
@pos = i
@enums[i].each(&block)
i += 1
end
self
end
......@@ -36,11 +42,10 @@ class Enumerator
end
def rewind
i = @enums.size - 1
while 0 <= i
e = @enums[i]
while 0 <= @pos && @pos < @enums.size
e = @enums[@pos]
e.rewind if e.respond_to?(:rewind)
i -= 1
@pos -= 1
end
self
......
......@@ -76,13 +76,24 @@ assert("Enumerator::Chain#size") do
end
assert("Enumerator::Chain#rewind") do
rewound = []
rewound = nil
e1 = [1, 2]
e2 = (4..6)
(class << e1; self end).define_method(:rewind) { rewound << __id__ }
(class << e2; self end).define_method(:rewind) { rewound << __id__ }
c = e1.chain(e2).each{}.rewind
assert_equal [e2.__id__, e1.__id__], rewound
(class << e1; self end).define_method(:rewind) { rewound << self }
(class << e2; self end).define_method(:rewind) { rewound << self }
c = e1.chain(e2)
rewound = []
c.rewind
assert_equal [], rewound
rewound = []
c.each{break c}.rewind
assert_equal [e1], rewound
rewound = []
c.each{}.rewind
assert_equal [e2, e1], rewound
end
assert("Enumerator::Chain#+") do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment