Indexing and loops¶
Arbor uses zero-based indexing, explicit range boundaries, and structured loops. Loop else has a precise empty-iteration meaning.
Design documentation
This chapter describes the language design. Examples are illustrative; implementation availability and unresolved rules are explained in Design status.
Boundary examples¶
For a list with five elements, values[0] addresses the first element and
values[4] the last. values[-1] and values[5] are invalid. The slice
values[2..<5] contains the final three elements; an end bound beyond the
collection is invalid rather than silently clipped.
A for loop that receives even one element skips its else, including when
that element immediately triggers break or continue.
Indices and ranges¶
Indexing is zero-based. Negative indices are invalid. Out-of-bounds access raises a declared exception; explicit last-element operations cover end-relative use.
Ranges distinguish exclusive and inclusive ends:
0..<5 // 0, 1, 2, 3, 4
1..=5 // 1, 2, 3, 4, 5
values[2..<5] // Elements 2, 3, 4
Slices are half-open. Equal valid bounds produce an empty slice. Invalid bounds raise rather than silently clipping. Range steps, reversed ranges, open-ended slices, and exact result ownership remain open.
Loop forms¶
for value in values {
process(value)
}
for (index, value) in values.enumerate() {
...
}
while connection.is_open {
process_next()
}
loop {
if finished {
break
}
process_next()
}
while is retained; loop expresses unconditional repetition. C-style three-part
for is omitted from the v0.1 direction. Infinite iterators remain useful when
they supply values. Ordinary iteration lends read-only elements; explicit mutable
iteration lends exclusive mutable access. Structural mutation is disallowed while
the relevant iteration borrows are active.
Break depth¶
break means break 1. break N exits exactly N lexically enclosing loops. N is
a positive integer literal, and excess depth is a compilation error. It never
denotes a returned value. Cleanup runs for each exited ordinary scope.
loop {
for item in items {
if finished(item) {
break 2
}
}
}
continue is supported. Depth-qualified continue has not been selected.
Empty-iteration else¶
for user in users {
display(user)
} else {
display("No users")
}
This has Jinja-style meaning: else runs only if iteration produces zero elements. It does not mean Python's completion-without-break rule.
- One element followed by break does not trigger else.
- Immediately continuing still counts as having received an element.
- Iterator acquisition/advancement failures propagate and do not trigger else.
- The else block is outside that loop when calculating break depth.
- The rule applies to async iteration too.
- Else is not added to while or loop.