5

Ruby 3.3 Implements Range#reverse_each Method For Very Large or Beginless Ranges...

 5 months ago
source link: https://blog.saeloun.com/2024/01/09/ruby-3-3-range-reverse-each-for-begin-endless-ranges/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

Jan 9, 2024

authorImg

Prasanth Chaduvula

I'm a React, Javascript & Rails full-stack Software Engineer. I have been working remotely for the past two years in a remote village. Before joining as a Software Engineer I founded kwiq - a hyperlocal delivery startup to deliver things in remote villages.

1 minute read

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)

Share this post!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK