Atoll uses for for every kind of loop. The tokens between for and the body
select one of four forms.
| Form | Shape | Continues while |
|---|---|---|
| Iteration | for pattern in value { ... } |
The iterable yields another value |
| Condition | for condition { ... } |
The condition is true |
| Pattern consume | for pattern := expression { ... } |
The expression matches the pattern |
| Infinite | for { ... } |
A control-flow expression exits the loop |
There is no separate while or loop keyword.
Iterate over values
for pattern in value evaluates the iterable and binds each yielded value to
the pattern.
fn sum(values: []int): int {
mut total := 0
for value in values {
total += value
}
return total
}Ranges are iterable:
for index in 0..10 {
process(index)
}The binding position accepts patterns. Parentheses are optional for the top-level tuple shorthand.
for key, value in entries {
store(key, value)
}An underscore ignores a yielded value:
for _ in 0..3 {
retry()
}Loop on a condition
for condition checks a bool before each iteration.
mut remaining := 3
for remaining > 0 {
tick(remaining)
remaining -= 1
}If the first check is false, the body does not run.
Consume matching values
for pattern := expression evaluates the expression before every iteration.
If the result matches, the pattern’s bindings are available in the body. If it
does not match, the loop ends.
for Some(message) := inbox.next() {
handle(message)
}Conceptually, this is repeated pattern matching with the non-matching case
exiting the loop. It is useful for consuming Option values, iterator
protocols, queues, and other stateful sources.
Loop indefinitely
A subjectless for repeats until its body transfers control elsewhere.
for {
message := receive()
if message.is_shutdown() {
break
}
handle(message)
}Break with a value
Loops are expressions. break value supplies the loop’s result.
answer := for {
candidate := next_candidate()
if candidate.is_valid() {
break candidate
}
}All reachable value-bearing exits must agree on a result type. A loop without
a value-bearing break is normally used for control flow rather than assigned.
Continue
continue skips the rest of the body and starts the next iteration.
for value in values {
if value < 0 {
continue
}
consume(value)
}For a condition or pattern-consume loop, the head is evaluated again. For an iteration loop, the iterable is advanced.
Labels
Prefix a loop with 'name: and pass the label to break or continue when
nested loops make the target ambiguous.
'outer: for row in rows {
for cell in row {
if cell.is_terminal() {
break 'outer
}
}
}A labeled break may also carry a value:
found := 'search: for group in groups {
for item in group {
if matches(item) {
break 'search item
}
}
}How the parser distinguishes forms
After for, an immediate { selects the infinite form. Otherwise, a
top-level := selects pattern consumption, a top-level in selects
iteration, and the remaining shape is a boolean condition. Delimiters inside
the head do not affect that decision.