-
-
Notifications
You must be signed in to change notification settings - Fork 388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add specs for Range#reverse_each #1169
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
require_relative '../../spec_helper' | ||
|
||
ruby_version_is "3.3" do | ||
describe "Range#reverse_each" do | ||
it "works efficiently for very long Ranges of Integers" do | ||
(1..2**100).reverse_each.take(3).size.should == 3 | ||
end | ||
|
||
it "works for beginless Ranges of Integers" do | ||
(..5).reverse_each.take(3).should == [5, 4, 3] | ||
end | ||
|
||
it "works for Ranges of Strings by converting the Range to an Array first" do | ||
("a".."z").reverse_each.take(3).should == ["z", "y", "x"] | ||
end | ||
|
||
it "raises a TypeError for endless Ranges of Integers" do | ||
-> { | ||
(1..).reverse_each.take(3) | ||
}.should raise_error(TypeError, "can't iterate from NilClass") | ||
end | ||
|
||
it "raises a TypeError for endless Ranges of other objects" do | ||
-> { | ||
("a"..).reverse_each.take(3) | ||
}.should raise_error(TypeError, "can't iterate from NilClass") | ||
end | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It makes sense to check the following files and have here the similar cases/structure:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All these tests are pretty specific for ranges. There is a spec in it "raises a TypeError beginless ranges" do
-> { (..2).each { |x| x } }.should raise_error(TypeError)
end This specific case is not relevant for arrays, you can simply reverse iterate over it, there is no need there to construct a temporary array and there is no chance for it to become infinite. As for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this test fails in case
#reverse_each
works inefficiently.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is very much skirting the (MRI) implementation.
A Range is pretty much just a combination of a begin value, an end value, and an operation to get to the next value. In MRI 3.2 and below, there is no way to get to the previous value, so this code creates an array of
2**100
elements, then takes the last three elements of this array. So in MRI 3.2, this will result in either aNoMemoryError
or an extremely long evaluation/timeout.MRI 3.3 added a specialization for this method when using Integer values, this code now boils down to something like
[2**100, (2**100).pred, (2**100).pred.pred]
and finishes "instantly"This specialization currently only exists for Integer values, that's why there I've added a spec for the a-z-Range as well, to ensure other types still work.