yet another 「例外を投げない」言語

[「例外を投げない」という選択肢をとる言語](https://qiita.com/suin/items/bf67ceaba72a9cdcb1ac)

という記事がトレンドに乗ってたので・・

**Rustなのか？Rustなのかい？**

って思って開いてみた所・・・

```golang
ok, err := foo()
```

ってやった場合と

```golang
val, ok := bar["key"]
```

みたいにやった時に何がokなんだかよくわかんなくなる方の言語でした。
いや、使い方が悪いんでしょうけど。
最初、```if val, ok := bar["key"]; ok{ ...```みたいなコード見て混乱した覚えがあります。keyがあれば値が入るし、keyがないとfalseが返ってくる。ちょっと気持ち悪い。

ってごめんなさい。Goも好きです。disってないです。

## Rustの場合

で、自分的に「例外を投げない」でピンと来た方がこちら。
Rust初心者なのですが生意気にすいません。
Rustも例外のない言語です。
仕様的にはGoに近くて多値返却ではあるんですが、その多値を受け取る型が用意されています。
失敗する可能性のある関数だとすんなりとString型とかを返却する事はなくて、そのStringを```なんらかの形```でwrapして返す。
なので受け取ったStringを使いたかったらその```なんらかの形```から取り出して使うしかない。

Rustのエラーハンドリング
https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/error-handling.html

### Result型

こういう感じの列挙型です

```Rust
pub enum Result<T, E> {
    Ok(T),
    Err(E),
}
```

例えばファイルを開く```std::fs::File::open``` は開こうと思ったファイルの存在やら権限やらによっては失敗する関数です。
シンプルに開くだけの例だとこんな感じです。開こうとするとResultのenumが返却されるので、OkのパターンとErrのパターンに対応できる。

```Rust
use std::fs;

fn main() {
    //returns `io::Result<File>`
    match fs::File::open("foo.txt") {
        Ok(_f) => println!("opened foo.txt "),
        Err(_e) => panic!("couldn't open foo.txt "),
    }
}
```

### Option型

Someってなんやねん。判りづらい。。
正常な値が存在すれば```std::option::Option::Some``` を介して取り出せるって考えてればいいんだと思います。

```Rust
pub enum Option<T> {
    None,
    Some(T),
}
```

例えば、こんな感じでゼロ除算するとNoneの値が返って、それ向けに書いた処理が実行されます。
正常に割り切れたものは当然正常な処理が実行される。

```Rust
// An integer division that doesn't `panic!`
fn checked_division(dividend: i32, divisor: i32) -> Option<i32> {
    if divisor == 0 {
        // Failure is represented as the `None` variant
        None
    } else {
        // Result is wrapped in a `Some` variant
        Some(dividend / divisor)
    }
}

// This function handles a division that may not succeed
fn try_division(dividend: i32, divisor: i32) {
    // `Option` values can be pattern matched, just like other enums
    match checked_division(dividend, divisor) {
        None => println!("{} / {} failed!", dividend, divisor),
        Some(quotient) => {
            println!("{} / {} = {}", dividend, divisor, quotient)
        },
    }
}

fn main() {
    try_division(4, 2);
    try_division(1, 0);
}

//https://doc.rust-lang.org/rust-by-example/std/option.html
```


実行するとこんな感じに。

```Rust
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/rusttest`
4 / 2 = 2
1 / 0 failed!
```

こんな感じでいちいち値がwrapされる。
ちなみにこういう感じでwrapされてても```unwrap```とか使うと簡単に取り出す事はできる。
アンチパターンになりがちだけど、あっさり書いてもいい場所には使える。
```expect``` でそのままpanicにしちゃったりもできる。
https://doc.rust-lang.org/std/option/enum.Option.html#method.unwrap

```Rust
let x = Some("air");
println!("{}", x.unwrap());
```

#### std::collections::HashMap.get()

HashMapでgetしたときもOptionが返ってきます。
```unwrap()```しちゃうとこんな感じ。

```Rust
use std::collections::HashMap;

fn main(){
    let mut map = HashMap::new();
    map.insert("foo", "bar");

    println!("value is {}",map.get(&"foo").unwrap());
}
```

## Rustややこしい

Rustの **3大ややこしい** のうちの一つがこのエラー処理なのではなかろうか。
他の言語でぜんぜん馴染みないし。
でもプログラマがエラーを強制的に意識して書かなくてはいけないってのは安全なコードにつながるし、Rustの思想なんだと思う。

## 補足

例外はないけど、Dropトレイトっていうデストラクタはあるみたいです。try~catch的な事もできるかもしれないです。原則として後始末用なんだと思いますが。