while is noted in the language overview, but
is provisional. Control flow is important, and while is basic; the form is
similar in many languages, even if details may change.
C++: A couple example languages following C++'s syntax closely are Java and TypeScript.
while (x) {
DoSomething();
}
do {
DoSomethingElse();
} while (y);
Python: Python does not provide do/while. However, the else syntax for
having code execute if the condition is never true may be of interest.
while x:
DoSomething()
while True:
DoSomethingElse()
if not y:
break
while z:
print("z is true")
else:
print("z was never true")
Swift: Swift uses repeat instead of do.
while x {
DoSomething()
}
repeat {
DoSomethingElse()
} while y
Rust: Rust provides only a basic while loop, relying on the condition-less
loop to achieve do/while-like behavior.
while x {
DoSomething();
}
loop {
DoSomethingElse();
if (!y) { break; }
}
Go: Go has no while loops, only for loops. However, a for can be
written similar to a while.
for x {
DoSomething()
}
for {
DoSomethingElse();
if !y { break; }
}
Carbon should adopt while loop syntax consistent with C and C++. In
particular, it should adopt these three kinds of statements:
while: declares that we're doing a loop, containing the condition.continue: continues with the next loop iteration, starting with the loop
condition.break: breaks out of the loop, without testing the loop condition.Loop syntax looks like:
while ( boolean expression ) { statements }While will evaluate the loop condition before each pass of the loop, only continuing if the loop condition is true. When the loop condition evaluates to false, the loop completes.
Similar to the
if/else proposal,
the braces are optional and must be paired ({ ... }) if present. When there
are no braces, only one statement is allowed.
continue will continue with the next loop iteration directly, skipping any
other statements in the loop body. The next loop iteration behaves as normal,
starting with the condition being tested.
break exits the loop immediately, without testing the condition.
All of this is consistent with C and C++ behavior.
%token WHILE
%token CONTINUE
%token BREAK
statement:
WHILE '(' expression ')' statement
| CONTINUE ';'
| BREAK ';'
| /* preexisting statements elided */
;
Note that continue and break should only be valid in a loop context.
This baseline syntax is based on C++, following the migration sub-goal Familiarity for experienced C++ developers with a gentle learning curve. To the extent that this proposal anchors on a particular approach, it aims to anchor on C++'s existing syntax, consistent with that sub-goal.
Alternatives will generally reflect breaking consistency with C++ syntax. While most proposals may consider alternatives more, this proposal suggests a threshold of only accepting alternatives that skew from C++ syntax if they are clearly better; the priority in this proposal is to avoid debate and produce a trivial proposal. Where an alternative would trigger debate, it should be examined by an advocate in a separate proposal.
do/whiledo/while is omitted from this proposal because of disagreement about whether
it should be included in Carbon. It's better to have do/while considered
separately as a result, in order to separate review of the non-contentious
while.
Relevant goals are:
3. Code that is easy to read, understand, and write:
while loops are easy to read and very helpful.7. Interoperability with and migration from existing C++ code:
Both alternatives from the
if/else proposal
apply to while as well: we could remove parentheses, require braces, or both.
The conclusions mirror here in order to avoid a divergence in syntax.
Additional alternatives follow.
Various non-C++ features that came up and are not suggested by this proposal because they aren't in C++ are:
else on while, as in Python.loop statement with while(true) behavior, as in Rust.These may be added later, but they are not part of the C++ baseline, and have not received much consideration beyond that adopting the proposed syntax would not significantly impair adoption of such features.
whileThis proposal does not offer a way to initialize variables in the while.
For comparison, C++ does allow declaring a variable in the condition, such as:
while (optional<T> next = get_next()) { ... }
In addition,
Selections statements with initializer
could be inferred to suggest a corresponding while (init; cond) syntax.
Neither of these is suggested in this proposal because we are likely to consider
a different route of allowing declaration of a variable in expressions. For
example, the following would be legal not because while would use a
condition semantic that allows variable declarations as a form, but because it
uses expression semantics and var would be part of expression semantics:
while (var optional<T> next = get_next()) { ... }
In particular, this would also allow more flexible usage addressing more complex use-cases that C++ does not, such as:
while ((var status_code c = bar()) != SUCCESS) { ... }`
This breaks slightly from the C++ baseline by offering a
subset of C++ functionality. However, we can choose to add related functionality
later if expression semantics end up not including var. Temporarily omitting
condition functionality avoids having to reconcile it later if we pursue the
expression route, and it is not crucial to while loop functionality.