web-dev-qa-db-ja.com

なぜifを使用して文字列を&strと比較できますが、matchを使用しているときはできませんか?

コマンドライン引数を読み取り、ハードコードされた文字列リテラルと比較する関数を実装しようとしています。

ifステートメントとの比較を行うと、魅力的に機能します。

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

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

しかし、matchステートメントを使用すると(よりエレガントになると思います):

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

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

Stringが予期されていたが&static str 発見された:

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`

私は Rustで文字列を文字列リテラルと照合する方法? を見たので、それを修正する方法を知っていますが、知りたいですなぜifを使用しても、matchを使用しない場合、比較は機能します。

10
robfuscator

ifを使用しても、matchを使用しない場合に比較が機能する理由を知りたいです。

条件で==を使用したため、ifなどについてはそれほど重要ではありません。 ifステートメントの条件は、bool型の式です。あなたはたまたまそこで==を使用することを選択したのです。

==演算子は、実際には PartialEq特性 に関連付けられた関数です。この特性は、任意のpairタイプに実装できます。そして、便宜上、StringにはPartialEq<str>PartialEq<&str>の実装があり、その逆も同様です。

一方、match式では、比較のために==ではなく パターンマッチング を使用します。 &'static strのような"holla!"リテラルは有効なパターンですが、完全に異なる型であるStringと一致することはありません。

パターンマッチングを使用すると、全体が等しくなくても、複雑な構造の部分を簡潔に比較したり、変数を一致の一部にバインドしたりできます。 Stringsは実際にはメリットがありませんが、他の型に対しては非常に強力であり、==とはまったく異なる目的を持っています。

if let構文を使用する代わりに、ifでパターンマッチングを使用できることに注意してください。あなたの例は次のようになります:

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

逆に、match内で==を使用する1つの方法は次のとおりです。

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

または、@ ljedrzが示唆したように:

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