Skip to content

For and For Let

Calibre uses for for several looping styles.

The most common form loops over a range or iterable value.

for i in 1..=10 => print(i);

You can also loop over lists directly.

let numbers := list:<int>[10, 20, 30];
for n in numbers => print(n);

If you need to mutate each item through a reference, you can loop over a mutable reference to the collection.

let mut lst : list:<int> = [1, 2, 3];
for n in &mut lst => {
*n *= 2;
};

for can also act like a while-style loop by using a boolean condition instead of in.

let mut countdown := 3;
for countdown > 0 => {
print(countdown);
countdown -= 1;
};

An empty condition creates an infinite loop.

for => {
print("looping");
break;
};

In Calibre for loops supports break, continue, and until.

for i in 0..10 => {
if i < 3 => continue;
if i == 8 => break;
print(i);
} until i > 4;

for can also be treated as an expression that produces a value.

When used this way, break some_value returns a value from the loop, and the else branch provides the value if the loop finishes without breaking with one.

In this example, the loop evaluates to 9 because that is the value passed to break.

let result := for i in 0..10 => {
if i > 8 => break i;
} else => {
0;
};
print(result);

If the loop never breaks with a value, the else branch is used instead.

let result := for i in 0..5 => {
if i > 8 => break i;
} else => {
0;
};
print(result);

This makes for useful not just for repetition, but also for search-like logic where you want the loop itself to compute a final result.

for let combines looping with pattern matching. The loop body only runs when the current value matches the pattern.

for let .Some : value <- some(99) => {
print(value);
break;
};

This is useful when looping over optional or enum-like values.

You can destructure enum payloads directly in for let.

type PairEnum := enum { Tuple : <int, int> };
for let .Tuple : x, y <- PairEnum.Tuple : (7, 8) => {
print(x + y);
break;
};

for let can also match ranges and bind matched values.

for let item @ in 0..4 <- [1, 5, 3, 7] => {
print(item);
};

List patterns work too.

for let [4, ..] <- [[4], [2, 3], [4, 8, 9]] => {
print("matched list");
};

Use plain for when you want to process every iteration value, and for let when you only want the iterations whose values match a specific pattern.