Ruby 3.3 Implements Range#reverse_each Method For Very Large or Beginless Ranges And Error Handling For Endless Ranges

In Ruby, a Range is an object that represents a range of values with a defined beginning and end. It’s a fundamental data structure used to express a sequence or span between two values, whether they are numeric, alphabetical, or even dates.

We have two ways to define ranges.

# Inclusive Range (includes both start and end values)

inclusive_range = (start_value..end_value)

inclusive_range = (1..5)  # Includes 1, 2, 3, 4, 5
# Exclusive Range (excludes the end value)

exclusive_range = (start_value...end_value)

exclusive_range = (1...5)  # Includes 1, 2, 3, 4 (excludes 5)

reverse_each

The Range#reverse_each method is used to iterate through a range of values in reverse order.

range.reverse_each { |item| block }
irb(main):001> (1..3).reverse_each { |num| puts num }
3
2
1
=> 1..3

Before

Using Range#reverse_each with very large or beginless or endless ranges never returns.

Under the hood Range#reverse_each uses Enumerable#reverse_each which is implemented with #to_a.

So we are virtually not able to use reverse_each for a very large or beginless or endless ranges, even if few elements are iterated on actually.

(1..3**100).reverse_each { |num| puts num }

# => It never returns and memory intense task.

(..3).reverse_each { |num| puts num }

# => It never returns and memory intense task.

(1..).reverse_each { |num| puts num }

# => It never returns and memory intense task.

After

Ruby 3.3 adds Range#reverse_each for Integer elements, So we can use reverse_each for a very large or beginless ranges. Ref PR

(1..3**100).reverse_each { |num| puts num }

# =>
515377520732011331036461129765621272702107522001
515377520732011331036461129765621272702107522000
515377520732011331036461129765621272702107521999
515377520732011331036461129765621272702107521998
515377520732011331036461129765621272702107521997

..continues
(..3).reverse_each { |num| puts num }

# =>
3
2
1
0
-1
-2
-3
...continues

With Ruby 3.3, Range#reverse_each for an endless range raises an exception, similar to Range#each for a beginless range. Ref PR

(1..).reverse_each { |num| puts num }

# =>
`reverse_each': can't iterate from NilClass (TypeError)

Need help on your Ruby on Rails or React project?

Join Our Newsletter