web-dev-qa-db-fra.com

Pourquoi puis-je comparer une chaîne à un & str en utilisant if, mais pas lors de l'utilisation de match?

J'essaie d'implémenter une fonction qui lit les arguments de ligne de commande et les compare aux littéraux de chaîne codés en dur.

Lorsque je fais la comparaison avec une instruction if, cela fonctionne comme un charme:

fn main() {
    let s = String::from("holla!");

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

Mais en utilisant une instruction match (qui, je suppose, serait plus élégante):

fn main() {
    let s = String::from("holla!");

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

Je reçois toujours une erreur du compilateur qu'un String était attendu mais un &static str a été trouvé:

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`

J'ai vu Comment faire correspondre une chaîne avec des littéraux de chaîne dans Rust? donc je sais comment le réparer, mais je veux savoir pourquoi la comparaison fonctionne lorsque if mais sans utiliser match.

10
robfuscator

Je veux savoir pourquoi la comparaison fonctionne lorsque if mais sans utiliser match.

Il ne s'agit pas tant de if et plus parce que vous avez utilisé == dans l'état. La condition dans une instruction if est toute expression de type bool; il se trouve que vous avez choisi d'utiliser == Là.

Le == L'opérateur est vraiment une fonction associée à le trait PartialEq . Ce trait peut être implémenté pour n'importe quelle paire de types. Et, pour plus de commodité, String a des implémentations pour PartialEq<str> et PartialEq<&str>, entre autres - et vice versa.

D'un autre côté, les expressions match utilisent correspondance de modèle pour la comparaison, pas ==. UNE &'static str littéral, comme "holla!", est un modèle valide, mais il ne peut jamais correspondre à un String, qui est un type complètement différent.

La correspondance de motifs vous permet de comparer de manière concise des parties de structures complexes, même si le tout n'est pas égal, ainsi que de lier des variables à des parties de la correspondance. Bien que Strings n'en bénéficient pas vraiment, il est très puissant pour d'autres types et a un objectif entièrement différent de ==.

Notez que vous pouvez utiliser la correspondance de motifs avec if en utilisant à la place if let construire. Votre exemple ressemblerait à ceci:

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

Inversement, une façon d'utiliser == à l'intérieur d'un match est comme ceci:

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

Ou, comme l'a suggéré @ljedrz:

match s == "holla!" {
    true => println!("it worked!"), 
    _ => println!("nothing")
}
18
Peter Hall