Ranges
Ranges feature prominently in Ki, as restricted numeric types, in loops, really just everywhere.
Range Types
range MonthOfYear [1..12]
range Positive [0..]
range Negative [-1.., -1]
A range
is a restricted numeric type. It only requires one bound (note
Positive
and Negative
above) and will also accept a third "step" argument
that defaults to 1 if not given.
Range Literals
A range literal is a generator
fn main() {
for n in [0..10] {
if n % 2 == 0 {
echo("${n}")
}
}
}
A range literal defines a generator with a start, an end, and a step. End and step are both optional; without an end, the range will continue infinitely, and without a step, the range will increment by 1.
fn main() {
val single_evens: [2..8, 2]
val single_evens_backwards: [8..2, -2]
val all_evens: [2.., 2]
}
These ranges are inclusive. If you want exclusive ranges:
fn main() {
single_evens: (1..9, 2)
single_evens_backwards: (9..1, -2)
all_evens: (1.., 2)
}
You can also mix (
and ]
, for the common C-style loop:
fn main() {
val fruits: array(["apple", "banana", "cherry"])
for (i in [0..fruits.length)) {
echo("Fruit ${i + 1}: fruits[i]")
}
}
Of course, you should use for-in
here.
A Word Of Warning
It is very easy to use (
when you meant ]
and vice-versa. We justified
using them despite this pitfall because they're far away on the keyboard, and
errors of logic are far less common than errors of typing. Further, they match
the interval notation used in mathematics. That said, there are very few
cases where numeric iteration is truly required. Use for-in
whenever
possible; moreover, if you find yourself using numeric iteration often,
consider refactoring to use the safer and more idiomatic for-in
.