class Range

A Range object represents an interval of values.

A range is useful for:

Creating Ranges

You can create an Range object explicitly with:

Range Bounds

A range may have a lower bound, an upper bound, both, or neither.

The bounds for a range are set when the range is created, and are immutable:

A range may be:

Bounded Ranges

A bounded range has definite values for both its begin and end values:

To create a bounded range with a Range literal, use the double-dot (included end) or triple-dot (excluded end) notation with definite begin and end values:

r = 0..4         # => 0..4   # Included end.
r.include?(0)    # => true
r.include?(4)    # => true   # Included.
r.include?(-1)   # => false
r.include?(5)    # => false
r.include?(:foo) # => false  # Not comparable.

r = 0...4        # => 0...4  # Exclude end.
r.include?(0)    # => true
r.include?(3)    # => true
r.include?(-1)   # => false
r.include?(4)    # => false  # Excluded.
r.include?(:foo) # => false  # Not comparable.

To create a bounded range with Range.new, give definite values for both begin and end:

r = Range.new(0, 4)       # => 0..4   # Include end.
r.include?(4)             # => true   # Included.
r = Range.new(0, 4, true) # => 0...4  # Exclude end.
r.include?(4)             # => false  # Excluded.

Beginless Ranges

A beginless range has a nil begin value and a definite end value. Such a range includes all comparable values that are less than or equal to to the end value.

To create a beginless range with a Range literal, use the double-dot or triple-dot notation with a nil begin value and a definite end value:

r = nil..4     # => ..4    # Include end.
r = ..4        # => ..4    # The leading nil may be omitted.
r.include?(4)  # => true   # Included.

r = nil...4    # => ...4   # Exclude end.
r = ...4       # => ...4   # The leading nil may be omitted.
r.include?(4)  # => false  # Excluded.

To create a beginless range with Range.new, give a nil begin value and a definite end value:

r = Range.new(nil, 4)       # => ..4    # Include end.
r.include?(4)               # => true   # Included.
r = Range.new(nil, 4, true) # => ...4   # Exclude end.
r.include?(4)               # => false  # Excluded.

Endless Ranges

An endless range has a definite begin value and a nil end value. Such a range includes all comparable values that are greater than or equal to to the begin value.

To create an endless range with a Range literal, use the double-dot or triple-dot notation with a definite begin value and a nil end value.

An endless range has no end value to exclude, so these ranges all have the same behavior:

0..nil  # => 0..
0..     # => 0..   # Trailing nil may be omitted.
0...nil # => 0...
0...    # => 0...  # Trailing nil may be omitted.

To create an endless range with Range.new, give a definite begin value and a nil end value.

As before, an endless range has no end value to exclude, so these ranges have the same behavior:

Range.new(0, nil)       # => 0..
Range.new(0, nil, true) # => 0...

Unbounded Ranges

An unbounded range is both beginless and endless. Such a range includes all comparable values.

To create an unbounded range with a Range literal, give both begin and end values as nil.

An unbounded range has no end value to exclude, so these range have the same behavior;

nil..nil  # => nil..nil
..nil     # => nil..nil   # The leading nil may be omitted.
nil..     # => nil..nil   # The trailing nil may be omitted.
nil...nil # => nil...nil
...nil    # => nil...nil  # The leading nil may be omitted.
nil...    # => nil...nil  # The trailing nil may be omitted.

To create an unbounded range with Range.new, give both begin and end values as nil.

As before, an unbounded range has no end value to exclude, so these range have the same behavior:

Range.new(nil, nil)       # => nil..nil
Range.new(nil, nil, true) # => nil...nil

Ranges and Other Classes

An object may be put into a range if its class implements instance method <=>. Ruby core classes that do so include Array, Complex, File::Stat, Float, Integer, Kernel, Module, Numeric, Rational, String, Symbol, and Time.

Example:

t0 = Time.now         # => 2021-09-19 09:22:48.4854986 -0500
t1 = Time.now         # => 2021-09-19 09:22:56.0365079 -0500
t2 = Time.now         # => 2021-09-19 09:23:08.5263283 -0500
(t0..t2).include?(t1) # => true
(t0..t1).include?(t2) # => false

A range can be iterated over only if its elements implement instance method succ. Ruby core classes that do so include Integer, String, and Symbol (but not the other classes mentioned above).

Iterator methods include:

Example:

a = []
(1..4).each {|i| a.push(i) }
a # => [1, 2, 3, 4]

Ranges and User-Defined Classes

A user-defined class that is to be used in a range must implement instance method <=>; see Integer#<=>. To make iteration available, it must also implement instance method succ; see Integer#succ.

The class below implements both <=> and succ, and so can be used both to construct ranges and to iterate over them. Note that the Comparable module is included so the == method is defined in terms of <=>.

# Represent a string of 'X' characters.
class Xs
  include Comparable
  attr_accessor :length
  def initialize(n)
    @length = n
  end
  def succ
    Xs.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'X' * @length
  end
end

r = Xs.new(3)..Xs.new(6) #=> XXX..XXXXXX
r.to_a                   #=> [XXX, XXXX, XXXXX, XXXXXX]
r.include?(Xs.new(5))    #=> true
r.include?(Xs.new(7))    #=> false

What’s Here

First, what’s elsewhere. Class Range:

Here, class Range provides methods that are useful for:

Methods for Creating a Range

Methods for Querying

Methods for Comparing

Methods for Iterating

Methods for Converting

Methods for Working with JSON

To make these methods available:

require 'json/add/range'