Control Flow
if / else
if (condition) {
// then branch
} else {
// else branch
}
The else branch is optional. Parentheses around the condition are required.
var x = 10;
if (x > 5) {
print "big";
} else {
print "small";
}
// Output: big
while
while (condition) {
// body
}
var i = 0;
while (i < 3) {
print i;
i = i + 1;
}
// Output: 0 1 2
for
The C-style for loop with initializer, condition, and increment:
for (var i = 0; i < 5; i = i + 1) {
print i;
}
for-in
Iterate over arrays or maps:
var items = ["a", "b", "c"];
for (var item in items) {
print item;
}
// Output: a b c
for-in Destructuring
When iterating over arrays of arrays, you can destructure each element directly in the loop variable:
for (var [i, val] in enumerate(["a", "b", "c"])) {
print "{i}: {val}";
}
// Output: 0: a 1: b 2: c
for (var [name, score] in zip(["Alice", "Bob"], [95, 87])) {
print "{name}: {score}";
}
// Output: Alice: 95 Bob: 87
This is equivalent to accessing each element by index inside the loop body but more concise.
match
A match expression evaluates a value against a series of patterns and returns the result of the matching arm. It can be used anywhere an expression is valid.
var label = match score {
100 -> "Perfect"
0 -> "Zero"
_ -> "Other"
};
Each arm is a pattern followed by -> and a result expression. Arms can use block expressions to compute their result:
val result = match value {
Result.Ok(v) -> {
val doubled = v * 2;
doubled + 1
}
Result.Error(e) -> -1
};
The last expression in a block arm (without a trailing semicolon) becomes the arm's value.
The _ wildcard matches any value. If no arm matches and there is no wildcard, the result is nil.
var x = match 42 {
0 -> "zero"
42 -> "forty-two"
_ -> "other"
};
print x;
// Output: forty-two
Patterns are compared using ==. Any expression can be used as a pattern:
var n = 5;
var result = match n {
2 + 3 -> "five"
_ -> "not five"
};
// Output: five
Match works with any value type -- numbers, strings, booleans, and function return values:
var icon = match type(value) {
"number" -> "#"
"string" -> "abc"
_ -> "?"
};
Since match is an expression, it can be used inline:
print match 1 + 1 {
2 -> "correct"
_ -> "wrong"
};
// Output: correct
Enum Destructuring
Match can destructure enum variants and bind their fields to local variables:
enum Result { Ok(value), Error(message) }
val msg = match Result.Ok(42) {
Result.Ok(v) -> "got {v}"
Result.Error(e) -> "err: {e}"
};
// Output: got 42
Simple enum variants match by identity:
enum Color { Red, Green, Blue }
val label = match Color.Red {
Color.Red -> "danger"
Color.Green -> "go"
_ -> "other"
};
// Output: danger
break
Exit the innermost loop immediately.
for (var i = 0; i < 10; i = i + 1) {
if (i == 3) break;
print i;
}
// Output: 0 1 2
continue
Skip to the next iteration of the innermost loop.
for (var i = 0; i < 5; i = i + 1) {
if (i == 2) continue;
print i;
}
// Output: 0 1 3 4