Ruby 3.4, Range#size Now Raises TypeError If The Range Is Not Iterable

In Ruby, a Range is an object that represents a range of values with a defined beginning and end. It is 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)  #=> [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)

#=> [1, 2, 3, 4]

Ruby Range#size method

Returns the number of elements in the range. Both the begin and the end of the Range must be Numeric, otherwise nil is returned.

(10..20).size   #=> 11

(10...20).size  #=> 10

('a'..'z').size #=> nil

Before

When the begin value of Range is a Float or Rational, “the count of elements” does not make sense. Such Ranges are not iteratable, suggesting there are no such things as “elements”.

Yet, Range#size of such Ranges returns an Integer and returns an Infinity for beginless

(0.51..5).size          #=> 5

(0.51..5.quo(2)).size   #=> 2

(5.quo(2)..10).size     #=> 8

(..1).size              #=> Infinity

It seems both begin and end values of a Range are rounded (Numeric#round) to the nearest Integer before Range#size is calculated.

After

In Ruby 3.4, Range#size raises TypeError if the range is not iterable.

(0.51..5).size          #=> can't iterate from Float (TypeError)

(0.51..5.quo(2)).size   #=> can't iterate from Float (TypeError)

(5.quo(2)..10).size     #=> can't iterate from Rational (TypeError)

(..1).size              #=> can't iterate from NilClass (TypeError)

Need help on your Ruby on Rails or React project?

Join Our Newsletter