Why does this code work? Are commas in match statements just a convention?
for (index, character) in argv[1].chars().enumerate() {
match character {
'a' | 'A' => {println!("{}: 'A'", index)}
'e' | 'E' => {println!("{}: 'E'", index)}
'i' | 'I' => {println!("{}: 'I'", index)}
'o' | 'O' => {println!("{}: 'O'", index)}
'u' | 'U' => {println!("{}: 'U'", index)}
_ => {
let consonant: Vec<_> = character.to_uppercase().collect();
println!("{}: {:?} is not a vowel", index, consonant[0])
}
}
Rust has an extremely powerful control-flow operator called match that allows us to compare a value against a series of patterns and then execute code based on which pattern matches.
Rust provides pattern matching via the match keyword, which can be used like a C switch . The first matching arm is evaluated and all possible values must be covered.
Patterns are a special syntax in Rust for matching against the structure of types, both complex and simple. Using patterns in conjunction with match expressions and other constructs gives you more control over a program's control flow.
Instead of matching on an element, call the method in the trait on it. TLDR: in Rust, to match over type, we create a trait, implement a function for each type and call it on the element to match. Surround it with backticks to mark it as code. Single backticks for inline code, triple backticks for code blocks.
Let's take a look what the Rust reference says about this:
MatchArms : ( MatchArm => ( BlockExpression ,? | Expression , ) )* MatchArm => ( BlockExpression | Expression ) ,?
What we can see here is that on the right side of =>
there is always an expression, but we distinguish between two types of expressions: BlockExpression and Expression. After a BlockExpression a comma is optional (denoted by the ?
), but after an normal expression the comma is required, except for the last match arm: there, the comma is always optional.
What is a BlockExpression? The reference defines it as basically two braces { }
with a list of statements and an optional tail expression.
So: commas at the end of match arms are optional if:
{}
).Unfortunately, the compiler doesn't quite agree with the reference. This works, for example:
match true {
false => if true {
"hi"
} else {
"no"
}
true => ""
};
Note that the right hand side of the first match arm is not a block expression, but an if-else-expression. So for the compiler the rule seems to be: if the right hand side ends with a closing brace }
, the comma is optional.
As for what is idiomatic:
}
, omit the comma.Do Rust match statements require commas?
No. Your own code proves that.
Why does this code work?
Because the designers of the language decided it should.
A match arm can have either an expression followed by a comma or a block without a comma.
Are commas in match statements just a convention?
No. When using braces, rustfmt removes the commas. Otherwise they are required.
How rustfmt puts your code:
for (index, character) in argv[1].chars().enumerate() {
match character {
'a' | 'A' => println!("{}: 'A'", index),
'e' | 'E' => println!("{}: 'E'", index),
'i' | 'I' => println!("{}: 'I'", index),
'o' | 'O' => println!("{}: 'O'", index),
'u' | 'U' => println!("{}: 'U'", index),
_ => {
let consonant: Vec<_> = character.to_uppercase().collect();
println!("{}: {:?} is not a vowel", index, consonant[0])
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With