Control flow¶
Candela has if, three loops, and match. Every body is a brace-delimited
block, and braces are never optional.
if / else¶
fn main() {
let temperature = 30;
if temperature > 25 {
print("warm");
} else if temperature > 10 {
print("mild");
} else {
print("cold");
}
}
The condition is not parenthesised. It is a bool expression: candela has no
truthiness, so compare explicitly rather than testing a number or a string. A
condition of another type is a compile error naming the type it has, and a
condition typed any is checked when it runs and raises bad_downcast on
anything but a bool; see errors. The same holds for
else if, for while, and for the expression form below.
if as an expression¶
An if written where a value is expected produces a value. Each branch is a
single expression with no semicolon, and an else branch is required so that
every path yields something.
while¶
while repeats a block for as long as its condition holds. The condition is a
bool, exactly as in an if, and a value of another type is rejected the same
way it is there.
for¶
for walks a range or a collection.
A range is written start..end and covers start up to but not including
end. Leaving the start out begins at zero.
Iterating a list binds each element in turn; iterating a map binds each key. Iterating a string binds each character as a one-character string.
fn main() {
for word in ["a", "b"] {
print(word);
}
let counts = {"x": 1, "y": 2};
for key in counts {
print(key, counts.get(key));
}
}
The loop variable belongs to the loop and is not in scope after it.
loop¶
loop repeats until something breaks out of it.
break and continue¶
break leaves the innermost loop; continue skips to its next iteration. Both
work in for, while, and loop.
match¶
match compares a value against a list of arms and runs the first that fits.
Arms are written pattern => { ... }, and _ is the catch-all. A match needs
at least one arm that is not the wildcard, and the wildcard comes last.
fn main() {
let code = 2;
match code {
1 => { print("one"); }
2 => { print("two"); }
_ => { print("something else"); }
}
}
Arms match by equality, so any type you can compare works, strings included.
fn main() {
match "b" {
"a" => { print("first"); }
"b" => { print("second"); }
_ => { print("other"); }
}
}
Matching an enum matches on the variant instead, and binds the payload; see Enums.
Blocks and scope¶
A bare { ... } is a block. It groups statements and scopes the variables
declared inside it, which is occasionally useful for keeping a temporary out of
the surrounding function.
Loop bodies, if branches, and match arms are blocks and scope the same way.
See Variables for the scoping rules.
A block holds statements. A fn declaration written inside one is a compile
error, since functions belong at the top level of the file. See
Functions.