Commit fc75cff1 authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto

Merge pull request #1859 from ksss/enumerator

Fix Enumerator
parents e893349e 44776476
...@@ -156,10 +156,10 @@ class Enumerator ...@@ -156,10 +156,10 @@ class Enumerator
return to_enum :with_index, offset unless block_given? return to_enum :with_index, offset unless block_given?
raise TypeError, "no implicit conversion of #{offset.class} into Integer" unless offset.respond_to?(:to_int) raise TypeError, "no implicit conversion of #{offset.class} into Integer" unless offset.respond_to?(:to_int)
n = offset.to_int n = offset.to_int - 1
each do |i| enumerator_block_call do |i|
yield [i,n]
n += 1 n += 1
yield [i,n]
end end
end end
...@@ -206,9 +206,9 @@ class Enumerator ...@@ -206,9 +206,9 @@ class Enumerator
# # => foo:2 # # => foo:2
# #
def with_object object def with_object object
return to_enum :with_object, offset unless block_given? return to_enum :with_object, object unless block_given?
each do |i| enumerator_block_call do |i|
yield [i,object] yield [i,object]
end end
object object
...@@ -255,6 +255,7 @@ class Enumerator ...@@ -255,6 +255,7 @@ class Enumerator
# enum.each(:y, :z) { |elm| elm } #=> :method_returned # enum.each(:y, :z) { |elm| elm } #=> :method_returned
# #
def each *argv, &block def each *argv, &block
obj = self
if 0 < argv.length if 0 < argv.length
obj = self.dup obj = self.dup
args = obj.args args = obj.args
...@@ -264,11 +265,16 @@ class Enumerator ...@@ -264,11 +265,16 @@ class Enumerator
else else
args = argv.dup args = argv.dup
end end
@args = args obj.args = args
end end
return self unless block_given? return obj unless block_given?
enumerator_block_call(&block)
end
def enumerator_block_call(&block)
@obj.__send__ @meth, *@args, &block @obj.__send__ @meth, *@args, &block
end end
private :enumerator_block_call
## ##
# call-seq: # call-seq:
......
...@@ -72,6 +72,21 @@ assert 'Enumerator#with_object' do ...@@ -72,6 +72,21 @@ assert 'Enumerator#with_object' do
assert_equal([55, 3628800], ret) assert_equal([55, 3628800], ret)
end end
assert 'Enumerator#with_object arguments' do
to_three = Enumerator.new do |y|
3.times do |x|
y << x
end
end
a = []
to_three_with_string = to_three.with_object("foo")
to_three_with_string.each do |x,string|
a << "#{string}:#{x}"
end
assert_equal ["foo:0","foo:1","foo:2"], a
end
assert 'Enumerator#inspect' do assert 'Enumerator#inspect' do
e = (0..10).each e = (0..10).each
assert_equal("#<Enumerator: 0..10:each>", e.inspect) assert_equal("#<Enumerator: 0..10:each>", e.inspect)
...@@ -89,6 +104,27 @@ assert 'Enumerator#each' do ...@@ -89,6 +104,27 @@ assert 'Enumerator#each' do
assert_equal([1], ary) assert_equal([1], ary)
end end
assert 'Enumerator#each arguments' do
obj = Object.new
def obj.each_arg(a, b=:b, *rest)
yield a
yield b
yield rest
:method_returned
end
enum = obj.to_enum :each_arg, :a, :x
assert_equal [:a, :x, []], enum.each.to_a
assert_true enum.each.equal?(enum)
assert_equal :method_returned, enum.each { |elm| elm }
assert_equal [:a, :x, [:y, :z]], enum.each(:y, :z).to_a
assert_false enum.each(:y, :z).equal?(enum)
assert_equal :method_returned, enum.each(:y, :z) { |elm| elm }
end
assert 'Enumerator#next' do assert 'Enumerator#next' do
e = 3.times e = 3.times
3.times { |i| 3.times { |i|
...@@ -379,8 +415,8 @@ assert 'Kernel#to_enum' do ...@@ -379,8 +415,8 @@ assert 'Kernel#to_enum' do
assert_raise(ArgumentError){ nil.to_enum } assert_raise(ArgumentError){ nil.to_enum }
end end
assert 'modifying existing methods' do assert 'modifying existing methods' do
assert_equal Enumerator, loop.class
e = 3.times e = 3.times
i = 0 i = 0
loop_ret = loop { loop_ret = loop {
...@@ -388,11 +424,66 @@ assert 'modifying existing methods' do ...@@ -388,11 +424,66 @@ assert 'modifying existing methods' do
i += 1 i += 1
} }
assert_nil loop_ret assert_nil loop_ret
end
assert_equal Enumerator, loop.class assert 'Integral#times' do
assert_equal Enumerator, 3.times.class a = 3
assert_equal Enumerator, [].each.class b = a.times
assert_equal Enumerator, [].map.class c = []
assert_equal Enumerator, {a:1}.each.class b.with_object(c) do |i, obj|
assert_equal Enumerator, (1..5).each.class obj << i
end
assert_equal 3, a
assert_equal Enumerator, b.class
assert_equal [0,1,2], c
end
assert 'Enumerable#map' do
a = [1,2,3]
b = a.map
c = b.with_index do |i, index|
[i*i, index*index]
end
assert_equal [1,2,3], a
assert_equal [[1,0],[4,1],[9,4]], c
end
assert 'Array#each_index' do
a = [1,2,3]
b = a.each_index
c = []
b.with_index do |index1,index2|
c << [index1+2,index2+5]
end
assert_equal [1,2,3], a
assert_equal [[2,5],[3,6],[4,7]], c
end
assert 'Array#map!' do
a = [1,2,3]
b = a.map!
b.with_index do |i, index|
[i*i, index*index]
end
assert_equal [[1,0],[4,1],[9,4]], a
end
assert 'Hash#each' do
a = {a:1,b:2}
b = a.each
c = []
b.each do |k,v|
c << [k,v]
end
assert_equal [[:a,1], [:b,2]], c.sort
end
assert 'Range#each' do
a = (1..5)
b = a.each
c = []
b.each do |i|
c << i
end
assert_equal [1,2,3,4,5], c
end end
...@@ -31,6 +31,8 @@ class Array ...@@ -31,6 +31,8 @@ class Array
# #
# ISO 15.2.12.5.11 # ISO 15.2.12.5.11
def each_index(&block) def each_index(&block)
return to_enum :each_index unless block_given?
idx = 0 idx = 0
while(idx < length) while(idx < length)
block.call(idx) block.call(idx)
...@@ -46,6 +48,8 @@ class Array ...@@ -46,6 +48,8 @@ class Array
# #
# ISO 15.2.12.5.7 # ISO 15.2.12.5.7
def collect!(&block) def collect!(&block)
return to_enum :collect! unless block_given?
self.each_index{|idx| self.each_index{|idx|
self[idx] = block.call(self[idx]) self[idx] = block.call(self[idx])
} }
......
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