Rust のOption, ResultそしてSome, None, Ok, Err, expect, unwrap, ?演算子,... なにこれ

# 概要
Rustを学んでいて最初に??と思ったのがよく出てくるOptionとResultとそれぞれのメソッドです。
なので、自分なりに使い方を調べて簡単にまとめたものです。

# ドキュメント

## Option
https://doc.rust-lang.org/std/option/enum.Option.html

```rust:Option定義
pub enum Option<T> {
    None,
    Some(T),
}
```

## Result

https://doc.rust-lang.org/std/result/enum.Result.html

 ```rust:Result定義
 pub enum Result<T, E> {
    Ok(T),
    Err(E),
}
 ```

 # 実行例

**Option**と**Result**はよく似ているので両方を併記します。

## データの生成

```rust
let o1: Option<i32> = Some(5);
println!("o1 value: {:?}", o1);
let o2: Option<i32> = None;
println!("o2 value: {:?}", o2);

let r1: Result<i32, String> = Ok(12);
println!("r1 value: {:?}", r1);
let r2: Result<i32, String> = Err("Error occurred".into());
println!("r2 value: {:?}", r2);
```
-  `Option<T>`の型Tが**i32**ので`Some`内の値は**i32**の型でなければならない
-  `Option<T>`のもう一つの値は`None`である
-  `Result<T, E>`の型Tが **i32** なので`Ok`内の値は **i32** の型でなければならない
    -  良く見るのは型Tが **()** のときで、このときは`Ok(())`となる
-  `Result<T, E>`の型Eが **String** なので`Err`内の値は **String** の型でなければならない

```:実行結果
o1 value: Some(5)
o2 value: None
r1 value: Ok(12)
r2 value: Err("Error occurred")
```

## unwrap, expect

これは`Some`や`Ok`内の値を取り出すが、`None`や`Err`のときは**panic**になる

```rust
let o1: Option<i32> = Some(5);
let o1_val: i32 = o1.unwrap();
println!("o1 value: {}", o1_val);
let r1: Result<i32, String> = Ok(12);
let r1_val: i32 = r1.unwrap();
println!("r1 value: {}", r1_val);

let o2: Option<i32> = Some(7);
let o2_val: i32 = o2.expect("o2 value is missing");
println!("o2 value: {}", o2_val);
let r2: Result<i32, String> = Ok(18);
let r2_val: i32 = r2.expect("r2 value is missing");
println!("r2 value: {}", r2_val);
```
```:実行結果
o1 value: 5
r1 value: 12
o2 value: 7
r2 value: 18
```
値がちゃんと取り出せています。
次はpanicになる例です。
```rust:Option unwrap
let o1: Option<i32> = None;
let o1_val: i32 = o1.unwrap();
println!("o1 value: {}", o1_val);
```
```:実行結果(panic)
thread 'main' panicked at src/main.rs:34:26:
called `Option::unwrap()` on a `None` value
```
`println!`は実行されず２行目でpanicになっています。

```rust: Option expect
let o1: Option<i32> = None;
let o1_val: i32 = o1.expect("o1 value is missing");
println!("o1 value: {}", o1_val);
```
```:実行結果(panic)
thread 'main' panicked at src/main.rs:48:26:
o1 value is missing
```

```rust:Result unwrap
let r1: Result<i32, String> = Err("Error occurred".into());
let r1_val: i32 = r1.unwrap();
println!("r1 value: {}", r1_val);
```
```:実行結果(panic)
thread 'main' panicked at src/main.rs:40:26:
called `Result::unwrap()` on an `Err` value: "Error occurred"
```


```rust: Result expect
let r1: Result<i32, String> = Err("Error occurred".into());
let r1_val: i32 = r1.expect("r1 value is missing");
println!("r1 value: {}", r1_val);
```

```:実行結果(panic)
thread 'main' panicked at src/main.rs:61:26:
r1 value is missing: "Error occurred"
```

次に`expect`の処理を`match`を使って表すと次のようになっている。


```rust
let o1: Option<i32> = Some(5);
//let o1_val: i32 = o1.expect("o1 value is missing");
let o1_val: i32 = match o1 {
    Some(val) => val,
    None => panic!("o1 value is missing"),
}; 
println!("o1 value: {}", o1_val);

let r1: Result<i32, String> = Err("Error occurred".into());
//let r1_val: i32 = r1.expect("r1 value is missing");
let r1_val: i32 = match r1 {
    Ok(val) => val,
    Err(err) => panic!("r1 value is missing: \"{}\"", err),
};
println!("r1 value: {}", r1_val);
```
```:実行結果
o1 value: 5

thread 'main' panicked at src/main.rs:77:21:
r1 value is missing: "Error occurred"
```

`Option`と`Result`は**enum**なので`match`文を使えばほとんどのことが出来ますが、それを簡単なメソッドでどう表現するだけだと思います。

## ?演算子

```rust:main.rs
fn main() -> Result<(), String> {
    println!("enter main");
    let rs: u32 = sub_func()?;
    println!("sub_func returned: {}", rs);
    Ok(())
}

fn sub_func() -> Result<u32, String> {
    println!("enter sub_func");
    Ok(10)
}
```
```:実行結果
enter main
enter sub_func
sub_func returned: 10
sub_func done
```
上記の例では戻り値が`Ok`だったので`?`は`unwrap`のように値を取り出しています。だからといってどこでも`?演算子`が使えるわけでもありません。`?演算子`が使えるのは、それを使う関数の戻り値が`Result`であることです。この例では`main`の戻り値が`Result`になっているから使えます。さらに`Err(E)`の型Eが同じでなければなりません。この例では`String`で同じになっています。

次は`sub_func`で`Err`にする。
```rust:main.rs
fn main() -> Result<(), String> {
    println!("enter main");
    let rs: u32 = sub_func()?;
    println!("sub_func returned: {}", rs);
    Ok(())
}

fn sub_func() -> Result<u32, String> {
    println!("enter sub_func");
    Err("sub_func error".into())
}
```
```:実行結果
enter main
enter sub_func
Error: "sub_func error"
```
`Err`が返ってくると`?演算子`は関数内の以降の処理を飛ばしてreturnさせる。さらに`panic`にはなっていない。
`match`を使って書き直すと次のようになります。
```rust
let rs = match sub_func(){
    Ok(val) => val,
    Err(err) => return Err(err),
};
```

`match`を使った例でもわかるように`Err(E)`の型Eが一致していないと使えないのは前述したと通りです。例では、型Eが`main`,`sub_func`共に`String`なので`?演算子`が使えた。



## その他のメソッド

### if let 
```rust
let o1: Option<i32> = Some(5);
if let Some(val) = o1 {
    println!("o1 value: {}", val);
} else {
    println!("o1 value is missing");
}
let r1: Result<i32, String> = Err("Error occurred".into());
if let Ok(val) = r1 {
    println!("r1 value: {}", val);
} else {
    println!("r1 value is missing: \"{}\"", r1.unwrap_err());
}
```

```:実行結果
o1 value: 5
r1 value is missing: "Error occurred"
```

`unwrap_err()`で`Err`の内容を取得できます。

### is_some(), is_ok()

```rust
let o1: Option<i32> = Some(5);
if o1.is_some(){
    println!("o1 value: {}", o1.unwrap());
} else {
    println!("o1 value is missing");
}

let r1: Result<i32, String> = Err("Error occurred".into());
if r1.is_ok() {
    println!("r1 value: {}", r1.unwrap());
} else {
    println!("r1 value is missing: \"{}\"", r1.unwrap_err());
}
```
```:実行結果
o1 value: 5
r1 value is missing: "Error occurred"
```

これらとは逆の`is_none()`, `is_err()`もあります。

### unwrap_or

`None`や`Err`のときに正常値とは別の値を設定することができます。

```rust
let o1: Option<i32> = None;
let o1_val = o1.unwrap_or(0);
println!("o1 value: {}", o1_val);

let r1: Result<i32, String> = Err("Error occurred".into());
let r1_val = r1.unwrap_or(-1);
println!("r1 value: {}", r1_val);
```
```:実行結果
o1 value: 0
r1 value: -1
```
当然`Some(5)`や`Ok(12)`のときはそれぞれ`5`や`12`になります。

この他には`unwrap_or_else`などもあります。

# 終わりに

`Option`や`Result`で使えるメソッドはたくさんあって使い方や名前を覚えるのが大変です。その他のメソッドについてはマニュアルを参照すると良いと思います。
記事を書くことで理解が深まった気がします。