What is the difference between the way match and == are processed

I've seen statements like "if is just syntactic sugar for match", but why does this code work

fn main() {
    let a = String::from("hello");

    if a == "hello" {
        println!("if = {}", a);
    }
}

and this code does not

fn main() {
    let a = String::from("hello");

    match a {
        "hello" => println!("match = {}", a),
    }
}

I know that the compiler tells me "expected String, found &str", but why doesn't the if statement complain?

I see I messed up the formatting. This is my first post, but I think you can figure it out.

As you can tell, that statement is wrong. The left side of the match arm uses a pattern, while the equality comparison uses expressions on both sides.

The == operator uses the implementation of the PartialEq and Eq traits.

1 Like

But == is not if. if processes bools, not arbitrary comparisons. The way you can rewrite an if to match is:

match a == "hello" {
    true => println!("if = {}", a),
    false => {},
}

This is still not quite the same, because the match will accept &bool whereas if will not, but it's very similar. “Is syntactic sugar for” is an exaggeration, but they are very similar.

PartialEq trait implementations, not deref coercions.

3 Likes

Yup. I didn't go that route since I thought the OP was confused about patterns vs. expression, but I might have misunderstood it.

Yeah, I should have left the deref coercions part out. I have edited my answer.

by using _ (underscore) rust complies code to undefined because match need string to be defined and undefined

fn main() {
    let a = String::from("hello");

    match a.as_str() {
        "hello" => println!("match = {}", a),
         _ => ()
    }
}

Your wording is a bit unprecise. First of all, your code still doesn't compile because the types still don't match (pun not intended). You need to take a slice from the original string to make it work

fn main() {
    let a = String::from("hello");

    match &a[..] {
        "hello" => println!("match = {}", a),
         _ => ()
    }
}

See the &a[..] expression which has type &str like the match arms.
Second, the _ pattern does not stand for "undefined" but is a so called wildcard. It basically means "match anything". The reason you need this wildcard here is because match statements are exhaustive. That means that the match arms need to cover every possible value of type &str. Because &str is variable length there are infinetely many possible values for the type &str. Therefore, you need a default match arm that applies if all other match arms failed to match. And in this case, that's the _ pattern.

1 Like

I usually prefer this syntax to convert strings to strs:

fn main() {
    let a = String::from("hello");

    match a.as_str() {
        "hello" => println!("match = {}", a),
         _ => ()
    }
}
1 Like

&*a ftw.

2 Likes

Thanks everyone for sharing your knowledge. I think I've got it now.