On this page:
Range
Sequence  Range
List  Range
..
..
..
..=
..=
..=
<..
<..
<..
<..=
<..=
<..=
Range.from_  to
Range.from_  to
Range.from_  to_  inclusive
Range.from_  to_  inclusive
Range.from
Range.from
Range.from_  exclusive_  to
Range.from_  exclusive_  to
Range.from_  exclusive_  to_  inclusive
Range.from_  exclusive_  to_  inclusive
Range.from_  exclusive
Range.from_  exclusive
Range.to
Range.to
Range.to_  inclusive
Range.to_  inclusive
Range.full
Range.full
Range.start
Range.end
Range.includes_  start
Range.includes_  end
Range.is_  empty
Range.canonicalize
Range.contains
Range.encloses
Range.is_  connected
Range.overlaps
Range.span
Range.gap
Range.intersect
List  Range.to_  list
Sequence  Range.to_  sequence
Sequence  Range.step_  by
8.16.0.2

8.9 Ranges🔗ℹ

A range, or an interval, represents a contiguous set of integers between two points. When the starting point is included, the range can be used as a sequence; in addition, when the ending point is not #inf, the range is listable. Generally, the starting point must be less than or equal to the ending point, so that the lower bound is “less than or equal to” the upper bound by comparison on bounds.

A range supports membership tests using the in operator, which is the same as Range.contains.

annotation

Range

 

annotation

SequenceRange

 

annotation

ListRange

The Range annotation matches any range.

The SequenceRange annotation matches a range that can be used as a sequence, for which Range.includes_start returns true.

The ListRange annotation matches a range that is listable, for which Range.includes_start returns true, and Range.end returns non-#inf.

Static information associated by SequenceRange or ListRange makes an expression acceptable as a sequence to for in static mode.

expression

start_expr .. end_expr

 

repetition

start_repet .. end_repet

 

binding operator

start_bind .. end_bind

 

expression

start_expr ..

 

repetition

start_repet ..

 

binding operator

start_bind ..

 

expression

.. end_expr

 

repetition

.. end_repet

 

binding operator

.. end_bind

 

expression

..

 

repetition

..

 

binding operator

..

 

~order: enumeration

The same as Range.from_to, Range.from, Range.to, and Range.full, respectively.

When start_expr .. end_expr or start_expr .. is used in an each clause of for, the optimization is more aggressive in that no intermediate range is created.

expression

start_expr ..= end_expr

 

repetition

start_repet ..= end_repet

 

binding operator

start_bind ..= end_bind

 

expression

..= end_expr

 

repetition

..= end_repet

 

binding operator

..= end_bind

 

~order: enumeration

The same as Range.from_to_inclusive and Range.to_inclusive, respectively.

When start_expr ..= end_expr is used in an each clause of for, the optimization is more aggressive in that no intermediate range is created.

expression

start_expr <.. end_expr

 

repetition

start_repet <.. end_repet

 

binding operator

start_bind <.. end_bind

 

expression

start_expr <..

 

repetition

start_repet <..

 

binding operator

start_bind <..

 

~order: enumeration

The same as Range.from_exclusive_to and Range.from_exclusive, respectively.

expression

start_expr <..= end_expr

 

repetition

start_repet <..= end_repet

 

binding operator

start_bind <..= end_bind

 

~order: enumeration

function

fun Range.from_to(start :: Int, end :: Int) :: ListRange

 

binding operator

Range.from_to(start_bind, end_bind)

Constructs a range that includes start, but does not include end. The corresponding binding matches the constructed range.

function

fun Range.from_to_inclusive(start :: Int, end :: Int)

  :: ListRange

 

binding operator

Range.from_to_inclusive(start_bind, end_bind)

Constructs a range that includes both start and end. The corresponding binding matches the constructed range.

function

fun Range.from(start :: Int) :: SequenceRange

 

binding operator

Range.from(start_bind)

Constructs a range that includes start, and with #inf as the ending point. The corresponding binding matches the constructed range.

function

fun Range.from_exclusive_to(start :: Int, end :: Int)

  :: Range

 

binding operator

Range.from_exclusive_to(start_bind, end_bind)

Constructs a range that does not include either start or end. Unlike the other constructors, start must be less than (but not equal to) end, otherwise the lower bound would be “greater than” the upper bound. The corresponding binding matches the constructed range.

Constructs a range that does not include start, but includes end. The corresponding binding matches the constructed range.

function

fun Range.from_exclusive(start :: Int) :: Range

 

binding operator

Range.from_exclusive(start_bind)

Constructs a range that does not include start, and with #inf as the ending point. The corresponding binding matches the constructed range.

function

fun Range.to(end :: Int) :: Range

 

binding operator

Range.to(end_bind)

Constructs a range with #neginf as the starting point, and does not include end. The corresponding binding matches the constructed range.

function

fun Range.to_inclusive(end :: Int) :: Range

 

binding operator

Range.to_inclusive(end_bind)

Constructs a range with #neginf as the starting point, and includes end. The corresponding binding matches the constructed range.

function

fun Range.full() :: Range

 

binding operator

Range.full()

Constructs a range with #neginf as the starting point and #inf as the ending point. The corresponding binding matches the constructed range.

method

method (rge :: Range).start() :: Int || matching(#neginf)

 

method

method (rge :: Range).end() :: Int || matching(#inf)

Returns the starting point and ending point of rge, respectively. The starting point can be #neginf, and the ending point can be #inf, indicating the lack of a starting point or ending point.

method

method (rge :: Range).includes_start() :: Boolean

 

method

method (rge :: Range).includes_end() :: Boolean

Returns #true if rge includes the starting point and the ending point, respectively, #false otherwise. A #neginf starting point or #inf ending point cannot be included.

method

method (rge :: Range).is_empty() :: Boolean

Returns #true if rge is an empty range, #false otherwise. An empty range is empty “by definition,” meaning that its lower bound is “equal to” its upper bound, and therefore it cannot have anything at all in the range that it represents. By contrast, a range may have no integers even if its lower bound is strictly “less than” its upper bound (but it may well have real numbers, in principle); in such case, use rge.canonicalize().is_empty() to check for its “emptiness.”

> (3..4).is_empty()

#false

> (3..=3).is_empty()

#false

> (3..3).is_empty()

#true

> (3 <..= 3).is_empty()

#true

> (3 <.. 4).is_empty()

#false

> (3 <.. 4).canonicalize().is_empty()

#true

method

method (rge :: Range).canonicalize() :: Range

Returns the canonical form of rge with respect to the discrete domain of integers. The canonical form has and only has all integers that rge has, and is guaranteed to be in one of the following forms:

Furthermore, if rge is already in canonical form, it is returned as-is.

> (1..5).canonicalize()

1 .. 5

> (1..).canonicalize()

1 ..

> (..5).canonicalize()

.. 5

> (..).canonicalize()

..

> (1..=5).canonicalize()

1 .. 6

> (..=5).canonicalize()

.. 6

> (1 <.. 5).canonicalize()

2 .. 5

> (1 <..).canonicalize()

2 ..

> (1 <..= 5).canonicalize()

2 .. 6

method

method (rge :: Range).contains(int :: Int) :: Boolean

Checks whether rge has int in the range that it represents. See also in.

> (3..=7).contains(5)

#true

> (3..=7).contains(7)

#true

> (3..=7).contains(10)

#false

> 5 in 3..=7

#true

method

method (rge :: Range).encloses(another_rge :: Range, ...) :: Boolean

 

function

fun Range.encloses(rge :: Range, ...) :: Boolean

Checks whether the given ranges are in enclosing order. A range rge encloses another range rge2 when rge has every integer in rge2. Every range encloses itself, and empty ranges never enclose non-empty ranges.

> Range.encloses()

#true

> (2 <.. 8).encloses()

#true

> (2 <.. 8).encloses(4..=6)

#true

> (2 <.. 8).encloses(2..=6, 4..=6)

#false

> (2 <.. 8).encloses(5..)

#false

> (2 <..).encloses(5..)

#true

method

method (rge :: Range).is_connected(rge2 :: Range) :: Boolean

Checks whether rge is connected with rge2, that is, whether there exists a range (possibly empty) that is enclosed by both rge and rge2.

> (2..=7).is_connected(3 <.. 8)

#true

> (2..=5).is_connected(5 <.. 8)

#true

> (2 <.. 5).is_connected(5 <.. 8)

#false

method

method (rge :: Range).overlaps(rge2 :: Range) :: Boolean

Checks whether rge overlaps with rge2, that is, whether there exists a non-empty range that is enclosed by both rge and rge2.

> (2..=7).overlaps(3 <.. 8)

#true

> (2..=5).overlaps(5..=8)

#true

> (2..=5).overlaps(5 <.. 8)

#false

method

method (rge :: Range).span(another_rge :: Range, ...) :: Range

Returns the smallest range that encloses rgs and all rges.

> (2..=5).span()

2 ..= 5

> (2..=5).span(8 <.. 9)

2 .. 9

> (..4).span(6..=6)

..= 6

> (2 <.. 8).span(..=5, 8 <.. 9)

.. 9

method

method (rge :: Range).gap(rge2 :: Range) :: maybe(Range)

Returns the largest range that lies between rge and rge2, or #false if no such range exists (precisely when rge overlaps with rge2).

> (2..=5).gap(8..=9)

5 <.. 8

> (..4).gap(6..=6)

4 .. 6

> (2 <.. 8).gap(8..=10)

8 .. 8

> (2..=8).gap(8..=10)

#false

method

method (rge :: Range).intersect(another_rge :: Range, ...)

  :: maybe(Range)

 

function

fun Range.intersect(rge :: Range, ...) :: maybe(Range)

Returns the intersection of the given ranges, or #false if no such range exists. The intersection of a range rge and another range rge2 is the largest range that is enclosed by both rge and rge2, which only exists when rge is connected with rge2.

> Range.intersect()

..

> (2..=8).intersect()

2 ..= 8

> (2..=8).intersect(4 <.. 16)

4 <..= 8

> (4 <..).intersect(..6, 2..=8)

4 <.. 6

> (2 <.. 8).intersect(..=5)

2 <..= 5

> (2 <.. 8).intersect(8 <.. 10)

#false

method

method (rge :: ListRange).to_list() :: List

Implements Listable by returning a list of integers in rge in order.

Implements Sequenceable by returning a sequence of integers in rge in order. The sequence is infinite when the ending point is #inf.

Returns a sequence of integers in rge in order, stepping by the given step size.

When invoked as rge.step_by(step) in an each clause of for, the sequence is optimized, in addition to the optimization in .. or ..=.