Match forms
Use match when code should handle several possible shapes or values in one
place. It is especially useful for unions, because the compiler can check
whether every case is handled.
Raven supports match in expression and statement positions. The normal
expression form is keyword-first so it reads the same way as statement-form
match, which matches the shape most programmers expect:
- Expression form:
match scrutinee { ... } - Statement form:
match scrutinee { ... } - Postfix expression form:
scrutinee match { ... }
The postfix expression form remains valid for composition cases where the
scrutinee is already a prefix expression, such as
try Convert.ToInt32(text) match { ... }.
In statement context, match scrutinee { ... } is parsed as a
MatchStatementSyntax before expression statements are considered. The
keyword-first match expression form is used only when the parser is already
expecting an expression, such as after =, return, an argument separator, or
another expression-only position.
Both forms use the same pattern rules and diagnostics, including exhaustiveness checking and unreachable-arm detection.
In expression form, the match result is the selected arm expression value. In
statement form, the selected arm expression is evaluated and its resulting value
is discarded.
When statement-form match is the final statement in a value-returning body,
its selected arm value contributes an implicit tail return.
When a statement-form match computes arm values outside that implicit-return
position, the compiler reports warning RAV2107.
Likewise, statement-form if with an else branch contributes an implicit tail
return when it is the final statement in a value-returning body.
In statement form, arm block expressions are interpreted in statement context.
That means explicit return/throw statements inside those arm blocks are
valid. return exits the enclosing function/method and throw raises an
exception. In expression form, direct arm expressions may use return and
throw expressions, but statement return/throw inside block-expression arms
remains disallowed and reports RAV1900/RAV1907.
An exhaustive statement-form match whose arms all leave the current
control-flow region has no reachable endpoint. This includes arms that return
or throw, either directly or as the final operation of an arm block. A match
with missing coverage, a guard that can fail, or any arm that completes normally
still has a reachable endpoint.
Arm bodies accept any expression, including block expressions:
let label = match value {
0 => { "zero" }
_ => {
let text = "other"
text
}
}
match value {
0 => { Console.WriteLine("zero") }
_ => {
Console.WriteLine("other")
()
}
}
let label = try Convert.ToInt32(text) match {
Ok(let value) => "Parsed ${value}"
Error(_) => "Invalid"
}
An optional outer binding keyword may appear before a match-arm pattern:
match values {
let [first, second, ...rest] => first + second + rest.Length
_ => 0
}
match value {
let Some((x, y)) => x + y
_ => 0
}
match value {
let Some((x, y)) pair => pair.Value
_ => 0
}
For match arms, the outer binding keyword uses the same shorthand rule as
deconstruction assignment and for pattern targets: it supplies the binding
mode for otherwise bare captures inside the arm pattern. The same ambient
binding mode also applies to an optional trailing whole-pattern designation.
Mixing an outer binding keyword with inline pattern binding keywords in the same
arm is an error.
Statement-form match with block arms may use explicit return:
class Evaluator {
func Eval(scrutinee: bool) -> bool {
match scrutinee {
true => {
return true
}
false => {
return false
}
}
}
}