Ranges
A range represents some span over a set of values. Typically ranges will be over numbers, however any orderable set could be used for a range (e.g. strings, dates, etc.). Ranges are frequently used for loops, indexing, and several other places.
Ranges always contain a ..
and may include left and or right values that are juxtaposed, optionally specifying the bounds and step size.
Range Syntax
The syntax for ranges is inspired by Haskell syntax for ranges:
Like in haskell, you can use a tuple to include a second value to specify the step size.
Note:
[first..2ndlast,last]
is explicitly NOT ALLOWED, as it can have unintuitive behavior, and is covered by[first,second..last]
.
In addition, ranges can have their bounds be inclusive or exclusive. Inclusive bounds are indicated by square brackets, and exclusive bounds are indicated by parenthesis. The default is inclusive bounds. Also left and right bounds can be specified independently, so you can have a range that is inclusive on the left and exclusive on the right, or vice versa.
Juxtaposition
The left and right values are only considered part of the range if they are juxtaposed with the ..
. Values not juxtaposed with the range are considered separate expressions.
Note: the range juxtaposition operator has a quite low precedence. Most operators will have higher precedence, meaning the left and right expressions don't need to be wrapped in parenthesis. However, due to range juxtapose's low precedence, any range as part of an
in
expression (e.g.a in [A..B]
) must be wrapped in range bounds (i.e.[]
,(]
,[)
,()
) to ensure the range is parsed correctly.a in A..B
will be parsed as(a in A)..B
.
Multiple ranges can be used to index into multidimensional matrices
Numeric Ranges
Probably the most common type of range will be a numeric ranges which describes a span over real numbers.
Some simple examples include:
Ordinal Ranges
Ranges can also be constructed using any ordinal type. Currently the only only built in ordinal type other than numbers would be strings.
For example, the following range captures all characters in the range from 'a'
to 'z'
inclusive
All alphabetical characters might be represented like so
But I probably won't just be limited to individual characters. In principle you ought to be able to do something like this
which would create a range that consists of every possible 5 letter combination starting from the word 'apple'
and iterating through to the word 'zebra'
.
Note: this is distinct from every dictionary word in that range, as it will include many many gibberish words.
TDB exactly what criteria will be used for ordering strings, as I like string orderings that respect numbers embedded in them (e.g. 'apple2'
should come before 'apple10'
), but that becomes difficult with arbitrary strings. perhaps there might be a macro setting for the ordering type used
Range Uses
Ranges have a variety of different uses in Dewy.
Ranges in Loops
Probably the most common use is in conjunction with loops as a sequence to iterate over:
The above will print '0 1 2 3 4 5 '
.
To iterate over values in reverse, you can specify a reversed range:
This prints '5 4 3 2 1 0 '
.
Note: when specifying a reversed range, you must include the step size. Forgetting to specify the step size will result in an empty range, as ranges are normally increasing.
Range Arithmetic
Ranges can be used in arithmetic expressions, often as a way to construct new ranges.
Both of which will print '0 0.25 0.5 0.75 1 '
These are both equivalent to directly constructing the range [0,0.25..1]
, however the arithmetic versions are frequently more convenient.
This type of construction is closely related to the linspace()
/logspace()
functions in Dewy. TBD but linspace
/logspace
may in fact be implemented like so:
Compound Range Construction
Additionally you can construct more complex ranges by combining together multiple ranges:
The same range as above can be constructed using subtraction
Interval Membership
You can also check if a value falls within a specified range
Indexing Sequences
ranges can be used to select values from a sequence. For example, say we want a substring we can do the following
This works for any sequence type.
Note: only integer ranges can be used to index into sequences (TBD if this might be relaxed to real valued ranges).
Also, because array access is a juxtapose expression, we can easily make the selection inclusive or exclusive on either side.
You can specify that a range continues to the end of the sequence, or starts from the beginning by omitting the value for that side. This will construct a range that goes to infinity in that direction, which will select all elements in that direction.
Paired with the special end
token which represents the index of the last element in a sequence, this provides the means to select any desired subset of a sequence.