From f15069338debcaab151b589de9bcc32acffa6ca0 Mon Sep 17 00:00:00 2001 From: mrkn Date: Mon, 6 Aug 2018 09:08:28 +0000 Subject: enumerator.c: Introduce Enumerator::ArithmeticSequence This commit introduces new core class Enumerator::ArithmeticSequence. Enumerator::ArithmeticSequence is a subclass of Enumerator, and represents a number generator of an arithmetic sequence. After this commit, Numeric#step and Range#step without blocks returned an ArithmeticSequence object instead of an Enumerator. This class introduces the following incompatibilities: - You can create a zero-step ArithmeticSequence, and its size is not ArgumentError, but Infinity. - You can create a negative-step ArithmeticSequence from a range. [ruby-core:82816] [Feature #13904] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64205 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- spec/ruby/core/numeric/shared/step.rb | 6 +++--- spec/ruby/core/numeric/step_spec.rb | 8 ++++---- spec/ruby/core/range/step_spec.rb | 27 +++++++++++---------------- 3 files changed, 18 insertions(+), 23 deletions(-) (limited to 'spec') diff --git a/spec/ruby/core/numeric/shared/step.rb b/spec/ruby/core/numeric/shared/step.rb index fa703b7554..f058c64a50 100644 --- a/spec/ruby/core/numeric/shared/step.rb +++ b/spec/ruby/core/numeric/shared/step.rb @@ -259,15 +259,15 @@ describe :numeric_step, :shared => true do describe "when no block is given" do it "returns an Enumerator when step is 0" do - 1.send(@method, *@step_args.call(2, 0)).should be_an_instance_of(Enumerator) + 1.send(@method, *@step_args.call(2, 0)).should be_an_instance_of(Enumerator::ArithmeticSequence) end it "returns an Enumerator when not passed a block and self > stop" do - 1.send(@method, *@step_args.call(0, 2)).should be_an_instance_of(Enumerator) + 1.send(@method, *@step_args.call(0, 2)).should be_an_instance_of(Enumerator::ArithmeticSequence) end it "returns an Enumerator when not passed a block and self < stop" do - 1.send(@method, *@step_args.call(2, 3)).should be_an_instance_of(Enumerator) + 1.send(@method, *@step_args.call(2, 3)).should be_an_instance_of(Enumerator::ArithmeticSequence) end it "returns an Enumerator that uses the given step" do diff --git a/spec/ruby/core/numeric/step_spec.rb b/spec/ruby/core/numeric/step_spec.rb index a932b4df73..54133f8810 100644 --- a/spec/ruby/core/numeric/step_spec.rb +++ b/spec/ruby/core/numeric/step_spec.rb @@ -23,23 +23,23 @@ describe "Numeric#step" do describe "when no block is given" do it "returns an Enumerator when step is 0" do - 1.step(5, 0).should be_an_instance_of(Enumerator) + 1.step(5, 0).should be_an_instance_of(Enumerator::ArithmeticSequence) end it "returns an Enumerator when step is 0.0" do - 1.step(2, 0.0).should be_an_instance_of(Enumerator) + 1.step(2, 0.0).should be_an_instance_of(Enumerator::ArithmeticSequence) end describe "returned Enumerator" do describe "size" do it "raises an ArgumentError when step is 0" do enum = 1.step(5, 0) - lambda { enum.size }.should raise_error(ArgumentError) + enum.size.should == Float::INFINITY end it "raises an ArgumentError when step is 0.0" do enum = 1.step(2, 0.0) - lambda { enum.size }.should raise_error(ArgumentError) + enum.size.should == Float::INFINITY end end end diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb index 3d5e75b033..c364600fb0 100644 --- a/spec/ruby/core/range/step_spec.rb +++ b/spec/ruby/core/range/step_spec.rb @@ -5,9 +5,9 @@ describe "Range#step" do ScratchPad.record [] end - it "returns an enumerator when no block is given" do + it "returns an arithmetic sequence when no block is given" do enum = (1..10).step(4) - enum.should be_an_instance_of(Enumerator) + enum.should be_an_instance_of(Enumerator::ArithmeticSequence) enum.to_a.should eql([1, 5, 9]) end @@ -263,7 +263,7 @@ describe "Range#step" do end describe "when no block is given" do - describe "returned Enumerator" do + describe "returned Enumerator::ArithmeticSequence" do describe "size" do it "raises a TypeError if step does not respond to #to_int" do obj = mock("Range#step non-integer") @@ -279,19 +279,9 @@ describe "Range#step" do lambda { enum.size }.should raise_error(TypeError) end - it "raises an ArgumentError if step is 0" do - enum = (-1..1).step(0) - lambda { enum.size }.should raise_error(ArgumentError) - end - - it "raises an ArgumentError if step is 0.0" do - enum = (-1..1).step(0.0) - lambda { enum.size }.should raise_error(ArgumentError) - end - - it "raises an ArgumentError if step is negative" do - enum = (-1..1).step(-2) - lambda { enum.size }.should raise_error(ArgumentError) + it "returns Float::INFINITY for zero step" do + (-1..1).step(0).size.should == Float::INFINITY + (-1..1).step(0.0).size.should == Float::INFINITY end it "returns the ceil of range size divided by the number of steps" do @@ -307,6 +297,11 @@ describe "Range#step" do (-5...5).step(2).size.should == 5 end + it "returns the ceil of range size divided by the number of steps even if step is negative" do + (-1..1).step(-1).size.should == 0 + (1..-1).step(-1).size.should == 3 + end + it "returns the correct number of steps when one of the arguments is a float" do (-1..1.0).step(0.5).size.should == 5 (-1.0...1.0).step(0.5).size.should == 4 -- cgit v1.2.3