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)