## Ranges

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 `(`q` `r`)` to “apply”`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.

`unbounded-range` `::=`
`[` `start-expression` `by:` `step-expression` `]`
| `[` `start-expression` `<:` `]`

The expression `[`start` by: `step`]` evaluates to an infinite sequence of values, starting with `start`, and followed by `(+ `start` `step`)`, `(+ `start` (* 2 `step`))`, and so on.

The syntax `[`start-expression` <:]` is shorthand for `[`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: `size`` is specified, then the resulting range is the first `size` elements of unbounded sequence.

In the `<: `end`` or `<=: `end`` cases then the sequence counts up: The `step` must be positive, and defaults to 1. The resulting values are those `x` such that `(< `x` `end`)`, or `(<= `x` `end`)`, respectively.

In the `>: `end`` or `>=: `end`` cases then the sequence counts down: The `step` must be negative, and defaults to -1. The resulting values are those `x` such that `(> `x` `end`)`, or `(>= `x` `end`)`, respectively.

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 `[>:]`.