Compiler doesn't understand match patterns properly

fn group(arg: &str) -> Vec<(char, usize)> {
    arg.chars().fold(vec![], |mut acc, cur| {
        match acc.last_mut() {
            Some((c, count)) if *c == cur => *count += 1,
            _ => acc.push((cur, 1)),
        }
        acc
    })
}

Here, I originally tried (cur, count) => *count += 1( Rust Playground) but that cur is being used as a wildcard instead of cur from lambda parameter. The if statement feels a bit hacky. Why does the compiler not understand it?

1 Like

It’s shadowing. The behavior of a match statement like

match t {
    (c, count) => …
    …
}

never depends on whether c is already defined or not. It always introduces a new variable instead; if there already was a c defined in an outer scope that variable becomes unnamable inside of the match arm, because it’s being “shadowed”. In general, match statements are meant for matching against constructors (or structs or enums), but there’s also the opetions of using literals (e.g. str or integer or char literals) or even consts.

To be totally accurate, the case of constants kind-of kills my entire argument above because if c was a const then it doesn’t work as a wildcard match anymore. So it does depend on whether c was defined before, just that variables don’t count, only consts. Or constructors of a unit struct or an imported unit variant of an enum (think e.g. None). But both of these exceptions conventionally are always capitalized though so when looking at a match statement above, you’d usually expect c to be introducing a binding, anything else would have serious potential for confusion.

Long story short, if you want to test equality for two variables, you’ll have to use ==; that’s an intentional language design and I wouldn’t consider it hacky :wink:

7 Likes

Because it's very helpful to be able to do things like match x { Some(x) => ... which wants the shadowing.

(This is also a very old semantic. You can look into Standard ML and you'll see that its case is a nearly exact match for Rust's match.)

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.