8.9 Ranges
A rangeSee Ranges in the Rhombus Guide for an introduction to ranges. represents a contiguous set of integers between two points. When the starting point is not #neginf, 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 | |
| |
annotation | |
| |
annotation | |
The SequenceRange annotation matches a range that can be used as a sequence. Such a range has a non-#neginf starting point.
The ListRange annotation matches a range that is listable. Such a range has a non-#neginf starting point and a non-#inf ending point.
Static information associated by SequenceRange or ListRange makes an expression acceptable as a sequence to for in static mode.
expression | |
| |
repetition | |
| |
binding operator | |
| |
expression | |
| |
repetition | |
| |
binding operator | |
| |
expression | |
| |
repetition | |
| |
binding operator | |
| |
expression | |
| |
repetition | |
| |
binding operator | |
| |
|
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 | |
| |
repetition | |
| |
binding operator | |
| |
expression | |
| |
repetition | |
| |
binding operator | |
| |
|
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 | |
| |
repetition | |
| |
binding operator | |
| |
expression | |
| |
repetition | |
| |
binding operator | |
| |
|
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 | |
| |
repetition | |
| |
binding operator | |
| |
|
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.
function | |
| |
binding operator | |
function | |
| |
| |
binding operator | |
function | |
| |
| |
binding operator | |
function | |
| |
binding operator | |
function | |
| |
| |
binding operator | |
method | |
| |
method | |
method | |
| |
method | |
#false
#false
#true
#true
#false
> (3 <.. 4).canonicalize().is_empty()
#true
start .. end, if rge.start() and rge.end() are both integers;
start .., if rge.start() is an integer and rge.end() is #inf;
.. end, if rge.start() is #neginf and rge.end() is an integer; or
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
#true
#true
#false
#true
> Range.encloses()
#true
#true
#true
#false
#false
#true
> (2..=7).is_connected(3 <.. 8)
#true
> (2..=5).is_connected(5 <.. 8)
#true
> (2 <.. 5).is_connected(5 <.. 8)
#false
#true
#true
#false
2 ..= 5
2 .. 9
..= 6
.. 9
5 <.. 8
4 .. 6
8 .. 8
#false
method | ||
| ||
function | ||
|
> Range.intersect()
..
2 ..= 8
4 <..= 8
4 <.. 6
2 <..= 5
#false
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5]
method | ||
|
i
[0, 1, 2, 3, 4]
i
[0, 1, 2, 3, 4]
method | ||
When invoked as rge.step_by(step) in an each clause of for, the sequence is optimized, in cooperation with the optimization in .., ..=, <.., or <..=.
i
[0, 2, 4]
i
[1, 4, 7, 10]
annotation | |
| |
annotation | |
Since the resulting sequence is in descending order, generally, the starting point must be greater than (as opposed to less than) or equal to the ending point. Moreover, each DescendingRange form corresponds to one of the SequenceRange forms. In particular, the same kind of optimization in SequenceRange forms also applies to DescendingRange forms.
The DescendingListRange matches a DescendingRange object that is also listable. These are precisely the possible results of ListRange.descending.
expression | ||
| ||
repetition | ||
| ||
expression | ||
| ||
repetition | ||
| ||
function | ||
| ||
function | ||
|
expression | ||
| ||
repetition | ||
| ||
expression | ||
| ||
repetition | ||
| ||
function | ||
| ||
| ||
function | ||
|
expression | |||
| |||
repetition | |||
| |||
function | |||
|
method | |
|
When invoked as rge.descending() in an each clause of for, the sequence is optimized, in cooperation with the optimization in .., ..=, <.., or <..=.
i
[4, 3, 2, 1, 0]
i
[4, 2, 0]
i
[10, 7, 4, 1]
> (0..5).descending().to_list()
[4, 3, 2, 1, 0]
[4, 3, 2, 1, 0]
> (0 <..= 5).descending().to_list()
[5, 4, 3, 2, 1]
[5, 4, 3, 2, 1]
[5, 4, 3, 2, 1]
[4, 3, 2, 1, 0]
method | ||
|
i
[5, 4, 3, 2, 1]
> for List (i in (5 >=.. 0).to_sequence()): // non-optimizing
i
[5, 4, 3, 2, 1]
method | ||
When invoked as rge.step_by(step) in an each clause of for, the sequence is optimized, in cooperation with the optimization in .., ..=, <.., <..=, or ListRange.descending.
i
[5, 3, 1]
i
[9, 6, 3, 0]