class Range

A Range object represents a collection of values that are between given begin and end values.

You can create an Range object explicitly with:

Beginless Ranges

A beginless range has a definite end value, but a nil begin value. Such a range includes all values up to the end value.

r = (..4)               # => nil..4
r.begin                 # => nil
r.include?(-50)         # => true
r.include?(4)           # => true

r = (...4)              # => nil...4
r.include?(4)           # => false

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

A beginless range may be used to slice an array:

a = [1, 2, 3, 4]
# Include the third array element in the slice
r = (..2)  # => nil..2
a[r]       # => [1, 2, 3]
# Exclude the third array element from the slice
r = (...2) # => nil...2
a[r]       # => [1, 2]

Method each for a beginless range raises an exception.

Endless Ranges

An endless range has a definite begin value, but a nil end value. Such a range includes all values from the begin value.

r = (1..)         # => 1..
r.end             # => nil
r.include?(50)    # => true

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

The literal for an endless range may be written with either two dots or three. The range has the same elements, either way. But note that the two are not equal:

r0 = (1..)           # => 1..
r1 = (1...)          # => 1...
r0.begin == r1.begin # => true
r0.end == r1.end     # => true
r0 == r1             # => false

An endless range may be used to slice an array:

a = [1, 2, 3, 4]
r = (2..) # => 2..
a[r]      # => [3, 4]

Method each for an endless range calls the given block indefinitely:

a = []
r = (1..)
r.each do |i|
  a.push(i) if i.even?
  break if i > 10
end
a # => [2, 4, 6, 8, 10]

A range can be both beginless and endless. For literal beginless, endless ranges, at least the beginning or end of the range must be given as an explicit nil value. It is recommended to use an explicit nil beginning and implicit nil end, since that is what Ruby uses for Range#inspect:

(nil..)    # => (nil..)
(..nil)    # => (nil..)
(nil..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'