Rust入門!15のエクササイズ2-3|最大値・最小値編:Rustの型推論は強力


メインデスクトップPCのハードディスクが壊れました。昨日がプライムデーでよかった。

新しい言語を学ぶ時の15のエクササイズ をrustでやっています。

課題

finding maximum/minimum among a list of numbers

解答

find_min_max.rs
use std::cmp;

fn find_min_max(x: &[i64]) -> (i64, i64) {
    let mut min: i64 = x[0];
    let mut max: i64 = x[0];
    let mut x_iter = x.iter();
    while let Some(i) = x_iter.next() {
        min = cmp::min(*i, min);
        max = cmp::max(*i, max);
    }
    return (min, max)
}

最大値、最小値を見つける関数はこんな感じです。イテレータを利用してみました。listとか配列とかその類のものに対して同じ処理を行うのは、言語ごとの特徴が現れていて好きです。

再帰的に比較するやり方や、forやwhileのループを回すやり方など色々あります。イテレータを使うのは、比較的よくある手法なのかな。

メイン関数はこちら

main.rs
fn main() {
    // 普通に定義
    let x_slice: &[i64] = &[8, 1, 7, 4, 0, 2, 6, 9, 3, 5];
    let (x_min, x_max) = find_min_max(x_slice);
    println!("{}", x_min); // 0
    println!("{}", x_max); // 9

    // rustの型推論は強力なので、宣言時に型を指定していなくてもi64のスライスだと推論してくれるらしい
    let y_slice = &[15, -43, 30000, -12345, 8];
    let (y_min, y_max) = find_min_max(y_slice);
    println!("{}", y_min); // -12345
    println!("{}", y_max); // 30000
}

こんな感じです。

スライス定義のやり方がどこに書いてあるのかわからず、調べるのに時間がかかりました。

型推論について補足

rustの型推論では、宣言時に型がわからなくても、後からわかれば良い、と言うことになっているらしいので試してみました。

type.rs
fn main() {
    let z_slice = &[0, 1, 2, 3, 4, 5, 6];
    let z_slice2 = example(z_slice);
    println!("{}", z_slice2[0]); // 0
}

fn example(y: &[i8]) -> &[i8] {
    return y
}

i8型のスライスをそのまま返すだけの関数を定義して、そこに代入すると問題なく動きます。これは、z_sliceがi8型のスライスであると推論されているからなので、

mismatch.rs
fn main() {
    let z_slice = &[0, 1, 2, 3, 4, 5, 6];
    let z_slice2 = example(z_slice);
    let (z_min, z_max) = find_min_max(z_slice);
}

このように両方に代入しようとすると、mismatched typesのエラーが出て怒られます。exampleはi8、find_min_maxはi64のスライスを引数にとるからです。

まとめ

  • イテレータすごい
  • Rustの型推論は強力

余談ですが、listをhead(list[0])とtail(それ以降)にパターンマッチさせるやり方ができないか模索しましたが、よくわかりませんでした。