Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I compare a String to a &str using if, but not when using match?

I'm trying to implement a function that reads command line arguments and compares them to hard-coded string literals.

When I do the comparison with an if statement it works like a charm:

fn main() {     let s = String::from("holla!");      if s == "holla!" {         println!("it worked!");     } } 

But using a match statement (which I guess would be more elegant):

fn main() {     let s = String::from("holla!");      match s {         "holla!" => println!("it worked!"),         _ => println!("nothing"),     } } 

I keep getting an error from the compiler that a String was expected but a &static str was found:

error[E0308]: mismatched types  --> src/main.rs:5:9   | 5 |         "holla!" => println!("it worked!"),   |         ^^^^^^^^ expected struct `std::string::String`, found reference   |   = note: expected type `std::string::String`              found type `&'static str` 

I've seen How to match a String against string literals in Rust? so I know how to fix it, but I want to know why the comparison works when if but not using match.

like image 315
robfuscator Avatar asked Apr 17 '18 19:04

robfuscator


People also ask

Why can't we use == to compare string objects?

You should not use == (equality operator) to compare these strings because they compare the reference of the string, i.e. whether they are the same object or not. On the other hand, equals() method compares whether the value of the strings is equal, and not the object itself.

Can == be used on strings?

== compares the exact values. So it compares if the primitive values are the same, or if the references (addresses) are the same. That's why == often doesn't work on Strings; Strings are objects, and doing == on two string variables just compares if the address is same in memory, as others have pointed out. .

Can I compare a string to a character?

In other words, strings are compared letter-by-letter. The algorithm to compare two strings is simple: Compare the first character of both strings. If the first character from the first string is greater (or less) than the other string's, then the first string is greater (or less) than the second.

Can you compare an object to a string?

Objects are compared using . equals(), and String is an object too, so they also have to be compared using . equals().


1 Answers

I want to know why the comparison works when if but not using match.

It's not so much about if and more because you've used == in the condition. The condition in an if statement is any expression of type bool; you just happen to have chosen to use == there.

The == operator is really a function associated with the PartialEq trait. This trait can be implemented for any pair of types. And, for convenience, String has implementations for PartialEq<str> and PartialEq<&str>, among others - and vice versa.

On the other hand, match expressions use pattern matching for comparison, not ==. A &'static str literal, like "holla!", is a valid pattern, but it can never match a String, which is a completely different type.

Pattern matching lets you concisely compare parts of complex structures, even if the whole thing isn't equal, as well as bind variables to pieces of the match. While Strings don't really benefit from that, it's very powerful for other types, and has an entirely different purpose than ==.

Note that you can use pattern matching with if by instead using the if let construct. Your example would look like this:

if let "holla!" = &*s {     println!("it worked!"); } 

Conversely, one way to use == inside a match is like this:

match s {     _ if s == "holla!" => println!("it worked!"),     _ => println!("nothing"), } 

Or, as @ljedrz suggested:

match s == "holla!" {     true => println!("it worked!"),      _ => println!("nothing") } 
like image 90
Peter Hall Avatar answered Sep 20 '22 14:09

Peter Hall