Rustを勉強する part5【ジェネリック型】

# 記事について
次のTour of Rustを用いて学んだ内容のメモになります。

https://tourofrust.com/

# ジェネリック型とは
ジェネリック型を使用することで、`struct`や`enum`を部分的に定義することが可能になる。
コンパイル時にコード内での使用状況に応じて、完全に定義されたバージョンを生成する。

Rustでは通常、インスタンスを生成するコードから最終的な型を推論できる。しかし、補助が必要な場合は、`：：<T>`演算子を使って明示的に指定する。この演算子は`turbofish`という名前でも知られている。
// 部分的に定義された構造体型
```Rust
struct BagOfHolding<T> {
    item: T,
}

fn main() {
    // 注意: ジェネリック型を使用すると、型はコンパイル時に作成される。
    // ::<> (turbofish) で明示的に型を指定
    let i32_bag = BagOfHolding::<i32> { item: 42 };
    let bool_bag = BagOfHolding::<bool> { item: true };
    
    // ジェネリック型でも型推論可能
    let float_bag = BagOfHolding { item: 3.14 };
    
    // 注意: 実生活では手提げ袋を手提げ袋に入れないように
    let bag_in_bag = BagOfHolding {
        item: BagOfHolding { item: "boom!" },
    };

    println!(
        "{} {} {} {}",
        i32_bag.item, bool_bag.item, float_bag.item, bag_in_bag.item.item
    );
}
```

# 値が無いことの表現
他の言語では値が存在しないことを表す`null`キーワードが用いられる。
`null`が存在しないRustでは、1つ以上の値を`None`によって代替するパターンが一般的である。
```Rust
enum Item {
    Inventory(String),
    // None は項目がないことを表す
    None,
}

struct BagOfHolding {
    item: Item,
}
```

# Option
Rustには次のような`Option`と呼ばれるジェネリックな列挙型が組み込まれており、`null`を使わずにnull許容な値を表現できる。
```Rust
enum Option<T> {
    None,
    Some(T),
}
```
この列挙型はとても一般的で、`Some`と`None`を使えばどこでもインスタンスを生成できる。
```Rust
// 部分的に定義された構造体型
struct BagOfHolding<T> {
    // パラメータ T を渡すことが可能
    item: Option<T>,
}

fn main() {
    // 注意: i32 が入るバッグに、何も入っていません！
    // None からは型が決められないため、型を指定する必要があります。
    let i32_bag = BagOfHolding::<i32> { item: None };

    if i32_bag.item.is_none() {
        println!("バッグには何もない！")
    } else {
        println!("バッグには何かある！")
    }

    let i32_bag = BagOfHolding::<i32> { item: Some(42) };

    if i32_bag.item.is_some() {
        println!("バッグには何かある！")
    } else {
        println!("バッグには何もない！")
    }

    // match は Option をエレガントに分解して、
    // すべてのケースが処理されることを保証できます！
    match i32_bag.item {
        Some(v) => println!("バッグに {} を発見！", v),
        None => println!("何も見付からなかった"),
    }
}

```

# Result
Rustには次のような`Result`と呼ばれるジェネリックな列挙型が組み込まれており、失敗する可能性のある値を返せる。
慣例的に、これを用いてエラー処理を行う。
```Rust
enum Result<T,E> {
    Ok(T),
    Err(E),
}
```
このジェネリック型はカンマで区切られた複数のパラメータ化された型を持つことに注意する必要がある。
この列挙型はとても一般的で、`Ok`と`Err`を使えばどこでもインスタンスを生成できる。
```Rust
fn do_something_that_might_fail(i:i32) -> Result<f32,String> {
    if i == 42 {
        Ok(13.0)
    } else {
        Err(String::from("正しい値ではありません"))
    }
}

fn main() {
    let result = do_something_that_might_fail(12);

    // match は Result をエレガントに分解して、
    // すべてのケースが処理されることを保証できます！
    match result {
        Ok(v) => println!("発見 {}", v),
        Err(e) => println!("Error: {}",e),
    }
}
```

# 失敗するかもしれないmain
main関数はResultを返すことができる。
```Rust
fn do_something_that_might_fail(i: i32) -> Result<f32, String> {
    if i == 42 {
        Ok(13.0)
    } else {
        Err(String::from("正しい値ではありません"))
    }
}

// main は値を返しませんが、エラーを返すことがあります！
fn main() -> Result<(), String> {
    let result = do_something_that_might_fail(12);

    match result {
        Ok(v) => println!("発見 {}", v),
        Err(_e) => {
            // エラーをうまく処理
            
            // 何が起きたのかを説明する新しい Err を main から返します！
            return Err(String::from("main で何か問題が起きました！"));
        }
    }

    // Result の Ok の中にある unit 値によって、
    // すべてが正常であることを表現していることに注意してください。
    Ok(())
}
```

# 簡潔なエラー処理
`Result`はよく用いられるので、Rustには`Result`を扱うための強力な演算子`?`が用意されている。
次の2つのコードは等価である。
```Rust
do_something_that_might_fail()?
```
```Rust
match do_something_that_might_fail() {
    Ok(v) => v,
    Err(e) => return Err(e),
}
```
使用例としては次。
```Rust
fn do_something_that_might_fail(i: i32) -> Result<f32, String> {
    if i == 42 {
        Ok(13.0)
    } else {
        Err(String::from("正しい値ではありません"))
    }
}

fn main() -> Result<(), String> {
    // コードが簡潔なのに注目！
    let v = do_something_that_might_fail(42)?;
    println!("発見 {}", v);
    Ok(())
}
```

# やっつけな Option/Result 処理
OptionとResultの両方には、`unwrap`と呼ばれる関数があり、簡単に値を取得するのに便利である。
`unwrap`は次のことを行う。
1. `Option`/`Result`内の値を取得する。 
2. 列挙型が`None`/`Err`の場合、`panic!`する。

以下の2つのコードは等価である。
```Rust
my_option.unwrap()
```
```Rust
match my_option {
    Some(v) => v,
    None => panic!("Rustによって生成されたエラーメッセージ!"),
}
```

同様に、
```Rust
my_result.unwrap()
```
```Rust
match my_result {
    Ok(v) => v,
    Err(e) => panic!("Rustによって生成されたエラーメッセージ!"),
}
```

よいRust使い(Rustacean)であるためには、可能な限り`match`文を使用すべきである。

# ベクタ型
最も有用なジェネリック型のいくつかはコレクション型である。
ベクタは構造体`Vec`で表される可変サイズのリストです。
マクロ`Vec!`を使用すると、簡単にベクタを生成できる。

`Vec`にはメソッド`iter()`があり、これによりベクタからイテレータを生成すれば、ベクタを簡単にforループに入れることができる。
```Rust
fn main() {
    // 型を明示的に指定
    let mut i32_vec = Vec::<i32>::new(); // turbofish <3
    i32_vec.push(1);
    i32_vec.push(2);
    i32_vec.push(3);

    // もっと賢く、型を自動的に推論
    let mut float_vec = Vec::new();
    float_vec.push(1.3);
    float_vec.push(2.3);
    float_vec.push(3.4);

    // きれいなマクロ！
    let string_vec = vec![String::from("Hello"), String::from("World")];

    for word in string_vec.iter() {
        println!("{}", word);
    }
}
```

### ベクタのメモリ
* `Vec`は構造体ですが、内部的にはヒープ上の固定リストへの参照を保持している。
* ベクタはデフォルトの容量で始まり、容量よりも多くの項目が追加された場合、ヒープ上により大きな容量の固定リストを生成して、データを再割り当てする。

# まとめ
ジェネリック型がどれだけのちからを発揮できるかを理解できた。