Skip to content

Ranges and Iterators

Calibre has a built-in range type, which you use with syntax like 0..10 or 1..=5.

The stdlib adds useful methods to range.

let r := 0..5;
print(r.len());
print(r.start());
print(r.end());
print(r.contains(3));
print(r.to_list());
print(r.sum());

Ranges can also be turned into iterators with .into_iter().

The stdlib defines several iterator types:

  • ListIter:<T> for lists
  • RangeIter for ranges
  • StrIter for strings

These types implement the stdlib Iter trait, which provides iterator-style methods such as:

  • .collect()
  • .map(...)
  • .filter(...)
  • .for_each(...)
  • .fold(...)
  • .any(...)
  • .all(...)
  • .find(...)
  • .count()
  • .take(...)
  • .skip(...)
  • .enumerate()
  • .step_by(...)
  • .partition(...)

For example:

let mapped := list:<int>[1, 2, 3].into_iter().map(fn (x : int) -> int => x * 10).collect();
let filtered := list:<int>[1, 2, 3, 4].into_iter().filter(fn (x : int) -> bool => x % 2 = 0).collect();
let folded := list:<int>[1, 2, 3, 4].into_iter().fold(0, fn (acc : int, x : int) -> int => acc + x);

You can also work with iterator values manually through .next().

let mut it : RangeIter = (0..3).into_iter();
print(it.next());
print(it.next());
print(it.next());
let mut it : RangeIter = (0..3).into_iter();
for let .Some : x => it.next() => print(x);

String iteration uses StrIter and yields char values.

let mut chars : StrIter = "abc".into_iter();
print(chars.next());