A range is an immutable sequence of values
that increase “linearly” - i.e. by a fixed amount.
Most commonly it’s a sequence of consequtive integers.
An example of the syntax is [3 <: 7]
which evaluates
to the sequence [3 4 5 6]
.
You can specify an explicit increment with a by:
option.
There are multiple ways to specify when the sequence stops.
For example [3 by 2 <=: 7]
is the even numbers from
3 up to 7 (inclusive, because of the <=
).
Ranges are very useful for loop indexes, or selecting a sub-sequence.
If you have a sequence q
and a range r
, and you
use the syntax (
to
“apply”q
r
)q
with the argument r
,
is result is to select elements of q
with indexes in r
.
("ABCDEFG" [1 by: 2 <: 7]) ⇒ "BDF"
A range can be unbounded, or non-finite, if you leave off
the end value. For example [3 by: 2]
is the odd integers starting at 3.
The expression [
evaluates to an
infinite sequence of values, starting with start
by: step
]start
, and followed by
(+
,
start
step
)(+
, and so on.
start
(* 2 step
))
The syntax [
is shorthand for start-expression
<:][
.
start-expression
by: 1]
bounded-range
::=
[
start-expression
[by:
step-expression
] range-end
]
range-end
::=
<:
end-expression
| <=:
end-expression
| >:
end-expression
| >=:
end-expression
| size:
size-expression
A bounded range takes an initial subsequence of the unbounded
range specified by the start-expression
and optional step-expression
.
The different end-expression
variants provide different
ways to specify the initial subsequence.
If size:
is specified, then the resulting range
is the first size
size
elements of unbounded sequence.
In the <:
or end
<=:
cases then
the sequence counts up: The end
step
must be positive, and defaults to 1.
The resulting values are those x
such that (<
,
or x
end
)(<=
, respectively.
x
end
)
In the >:
or end
>=:
cases then
the sequence counts down: The end
step
must be negative, and defaults to -1.
The resulting values are those x
such that (>
,
or x
end
)(>=
, respectively.
x
end
)
The start-expression
, step-expression
, and size-expression
must evaluate to real numbers, not necessarily integers.
For example: [1 by: 0.5 <=: 3.0]
is [1.0 1.5 2.0 2.5 3.0]
.
The two pseudo-ranges [<:]
and [>:]
are useful as
array indexes. They mean “all of the valid indexes” of the array being indexed.
For increasing index values use [<:]
; for decreasing
index values (i.e. reversing) use [>:]
.