Loops
Table of contents
Overview
Carbon provides loops using the while and for statements. Within a loop, the break and continue statements can be used for flow control.
Details
while
while statements loop for as long as the passed expression returns True. Syntax is:
while (boolean expression) {statements}
For example, this prints 0, 1, 2, then Done!:
var x: Int = 0;
while (x < 3) {
Print(x);
++x;
}
Print("Done!");
for
for statements support range-based looping, typically over containers. Syntax is:
for (patterninexpression) {statements}
For example, this prints all names in names:
for (name: strbuf in names) {
Print(name);
}
Note: A name binding in the pattern of a
forloop is a value binding by default. If a mutable loop variable is desired, the pattern can usevar. For example:for (var x: T in range).
To support iterating over user-defined types, the for loop is defined in terms of the Core.Iterate interface. A container type can implement the Core.Iterate interface to make it iterable with for.
Iterate interface
The Core.Iterate interface is defined as:
interface Iterate {
let ElementType: Copy & Destroy;
let CursorType: Destroy;
fn NewCursor(self) -> CursorType;
fn Next(self, ref cursor: CursorType) -> Optional(ElementType);
}
CursorType: A type that represents the current position in the iteration.ElementType: The type of the elements returned by the iteration.NewCursor: Returns a new cursor initialized to the start of iteration.Next: Advances the cursor and returns the next element, orNoneif the end of iteration has been reached. It takes the cursor by reference (ref cursor: CursorType), allowing the method to modify the cursor in-place.
TODO: Update this interface to be extended type generic once suitable language facilities exist.
Loop desugaring
A for loop of the form:
for (<pattern> in <range>) {
<statements>
}
is desugared to a loop that manages the cursor and checks the optional return values:
{
let range:? auto = <range>;
var cursor: auto = range.(Iterate.NewCursor)();
while (true) {
match (range.(Iterate.Next)(cursor)) {
case .Some(<pattern>) => { <statements> }
default => { break; }
}
}
}
TODO: The above uses the deduced extended type syntax
:? autofrom in-progress proposal #5389, and should be updated to match the final state of that proposal.
Note: Any temporaries in
<range>will remain live until the end of the loop.
break
The break statement immediately ends a while or for loop. Execution will resume at the end of the loop’s scope. Syntax is:
break;
For example, this processes steps until a manual step is hit (if no manual step is hit, all steps are processed):
for (step: Step in steps) {
if (step.IsManual()) {
Print("Reached manual step!");
break;
}
step.Process();
}
continue
The continue statement immediately goes to the next loop of a while or for. In a while, execution continues with the while expression. Syntax is:
continue;
For example, this prints all non-empty lines of a file, using continue to skip empty lines:
var f: File = OpenFile(path);
while (!f.EOF()) {
var line: strbuf = f.ReadLine();
if (line.IsEmpty()) {
continue;
}
Print(line);
}
Alternatives considered
References
- Proposal #340:
while - Proposal #353:
for - Proposal #618:
varordering - Proposal #623: Require braces
- Proposal #1885:
forstatement and user types - Proposal #7381: Adopt
refinCore.Iterate.Next