[Rust]Rustlingsで学ぼう(if)

Rust

Rustlingsとは

RustlingsはRustコードに慣れるための演習が詰まったパッケージです。
概要その他については以下を参照してください。

今回の演習

今回はif(関数)です。
The Bookでは「3.5. Control Flow(3.5. 制御フロー)」の一部「if式」になります

if

それではifの3問です。

if1

  Compiling of exercises/if/if1.rs failed! Please try again. Here's the output:
error[E0308]: mismatched types
 --> exercises/if/if1.rs:7:34
  |
7 | pub fn bigger(a: i32, b: i32) -> i32 {
  |        ------                    ^^^ expected `i32`, found `()`
  |        |
  |        implicitly returns `()` as its body has no tail or `return` expression
  |
note: consider returning one of these bindings
 --> exercises/if/if1.rs:7:15
  |
7 | pub fn bigger(a: i32, b: i32) -> i32 {
  |               ^       ^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.

これはエラーというよりもその前に関数biggerの内容を記述するようにコメントされています。

pub fn bigger(a: i32, b: i32) -> i32 {
    // Complete this function to return the bigger number!
    // Do not use:
    // - another function call
    // - additional variables
}

課題に合わせてifを使って記述しましょう。ちなみに前回のfunctionで学習した式と文を意識するといくつかの書き方があるので参考までに記述してみます。

pub fn bigger(a: i32, b: i32) -> i32 {
    if a > b {
        return a;
    }
    return b;
}
pub fn bigger(a: i32, b: i32) -> i32 {
    if a > b {
        return a;
    }
    b
}
pub fn bigger(a: i32, b: i32) -> i32 {
    if a > b {
        a
    } else {
        b
    }
}
pub fn bigger(a: i32, b: i32) -> i32 {
    if a > b { a } else { b }
}

最後はとてもRustっぽいですね。

if2

  Compiling of exercises/if/if2.rs failed! Please try again. Here's the output:
error[E0308]: mismatched types
  --> exercises/if/if2.rs:14:9
   |
10 | pub fn foo_if_fizz(fizzish: &str) -> &str {
   |                                      ---- expected `&str` because of return type
...
14 |         1
   |         ^ expected `&str`, found integer

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.

こちらは戻り値の型違いですね。関数の中身を見るとifの最初の条件にマッチした場合は文字列スライスを、マッチしない場合はintegerを返してしまっています。Rustは暗黙的型変換をしないために数値を文字列に変換しません。そのため、関数の戻り値はどんな条件でも同じ型である必要があります。

そこで同じ型を返すのですが、テストコードのassert_eq!をすべて正常終了させるためには3つの条件が必要そうです。

pub fn foo_if_fizz(fizzish: &str) -> &str {
    if fizzish == "fizz" {
        "foo"
    } else if fizzish == "fuzz" {
        "bar"
    } else {
        "baz"
    }
}

if3

⚠️  Compiling of exercises/if/if3.rs failed! Please try again. Here's the output:
error[E0308]: `if` and `else` have incompatible types
  --> exercises/if/if3.rs:15:9
   |
12 |       } else if animal == "snake" {
   |  ____________-
13 | |         3
   | |         - expected because of this
14 | |     } else {
15 | |         "Unknown"
   | |         ^^^^^^^^^ expected integer, found `&str`
16 | |     };
   | |_____- `if` and `else` have incompatible types

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.

元のコードは問題となる部分はこんな感じです。

    let identifier = if animal == "crab" {
        1
    } else if animal == "gopher" {
        2.0
    } else if animal == "snake" {
        3
    } else {
        "Unknown"
    };

if式について触れていませんが、Rustではifは式ですので値を返すことができます。そのため、このように代入することができます。値を返すということは関数と同じく、結果となる返す値はすべて型が一致する必要があります。

これを踏まえると、問題は2箇所です。そう、2.0"Unknown"を修正する必要があります。

    let identifier = if animal == "crab" {
        1
    } else if animal == "gopher" {
        2
    } else if animal == "snake" {
        3
    } else {
        4
    };

(最後は4である必要はなく、1、2、3以外のintegerであれば良いです。)

rustc --explain

今回はfunctionsで触れましたE0308(型違い)のエラーコードのみです。なので割愛します。

最後に

まだまだいっぱいありますね。ぼちぼちがんばります。

タイトルとURLをコピーしました