Q: Why do match expression need parenthesis for ops to the right but not left?

Quick question for my understanding, why is:

    num_apples * match num_apples.cmp(&40) {
        Ordering::Greater => 1u8 ,
        _ => 2u8,
    }

ok, but this is not ok:

     match num_apples.cmp(&40) {
        Ordering::Greater => 1u8 ,
        _ => 2u8,
    } * num_apples

the lack of ; means this should be an expression and the type of the first expression is known at compile so Mul should work, but it doesn't.

For block-tailed-expressions like match, when they appear in a position that a statement is valid, they are always treated as a statement. This ensures that the parse does not rely on types in the program, which is a very desirable property to keep syntax not interleaved with complicated and turing-complete type resolution.

6 Likes

Thank you!

Also, "lack of ;" would be an arbitrary-length lookahead and ambiguity; we don't rely on that either. The closing brace can be the end of the expression (match doesn't require a semicolon when used as a statement), and *num_apples could be the start of a new expression (dereferencing a pointer).

8 Likes

This is probably a somewhat stupid question, but why does match (or if for that mapneed a statement form at all? Why can't it just be expression whose value is discarded if used with a ;?

Do things like

let foo;
match bar {
    Some(_) => foo = 1;
    None => foo = 0;
}
// foo is now initialized

not work with expressions? I suppose I've never tried, but I don't immediately see a strong reason they couldn't.

EDIT: sorry I've realized I just answered my own question, it's so that they can used without a ; that they have a statement form, I got tripped up by the context.

Note that assignment expressions result in (), so you can do that like:

let foo;
match bar {
    Some(_) => foo = 1,
    None => foo = 0,
}
// foo is now initialized

That's what I should have written yes, I was wondering whether the initialization analysis would be able to observe that foo had been initialized in every execution path even if it's an expression rather than a statement.

Yes, it does see that the initialization is complete, even as a match expression, e.g. playground.