-
-
Notifications
You must be signed in to change notification settings - Fork 0
Iteration And Loops
Pudu has four loop forms. while repeats a Boolean condition, while let repeats a refutable
pattern, for consumes an iterable value, and loop expresses repetition whose exit determines
its value.
fn greatestPowerBelow(limit: Int) -> Int {
var value = 1
while value * 2 < limit { value = value * 2 }
value
}
The condition is evaluated before every iteration and must be Bool. A while expression
produces ().
while let is the direct form for a state that carries either another value or a stopping case.
The subject is re-evaluated before each iteration.
fn drain(start: Option[Int]) -> Int {
var current = start
var total = 0
while let Some(value) = current {
total = total + value
current = if value > 1 { Some(value - 1) } else { None }
}
total
}
The binding value belongs to one successful iteration. It is not visible after the loop. A
pattern that cannot fail is rejected because it would spell an unconditional loop indirectly.
fn sum(values: Array[Int]) -> Int {
var total = 0
for value in values { total = total + value }
total
}
Arrays yield their elements, strings yield characters, sets yield members, and maps yield
(key, value) pairs. A tuple can be decomposed directly in the loop head.
for (name, score) in scores {
print(name + ": " + show(score))
}
Built-in iteration order is deterministic for a given interpreter value. Programs should not use set or map order as a sorting contract; sort an array when order is part of the result.
loop continues until control leaves it. A break may carry the value of the loop.
let first = loop {
let candidate = nextCandidate()
if acceptable(candidate) { break candidate }
}
All reachable value-carrying breaks must agree on a type. A loop with no reachable break has
type Never, which can join an ordinary type at a control-flow boundary.
continue begins the next iteration of the selected loop. break leaves it. Both have type
Never at a valid boundary because evaluation does not continue at that expression.
Labels make an outer target explicit in nested loops. Unlabelled control selects the nearest enclosing loop. A label does not create a value or a new variable scope.
User-defined iteration implements Std.Iter.Sequence[S, T]. The state type S is explicit and
passed as a value.
trait Sequence[S, T] {
fn begin(self: &Self) -> S
fn advance(self: &Self, state: S) -> Option[(S, T)]
}
begin creates the initial state. Each advance returns the next state and element, or None to
end the sequence. This protocol supports lazy adapters without requiring hidden iterator mutation.
The current interpreter has substantial per-iteration overhead. Algorithmic improvements still matter—particularly avoiding repeated full scans—but source-level loop timings should not be read as native-backend performance. The benchmark history records evaluator and data-structure costs separately.
- Modules And Imports
- Values, Bindings, And Blocks
- Types And Inference
- Records, Sums, And Tuples
- Functions Generics And Traits
- Pattern Language
- Control Flow And Patterns
- Iteration And Loops
- Failure And Propagation
- Numbers And Collections
- Sets Maps And Sequences
- Keyed Structures
- Trees And Hierarchies
- Standard Library
- Output Formatting And Testing
- Tasks And Scopes
- Compile-Time Evaluation
- Typed Macros
- References And Unsafe
- Worked Programs