競プロで`Option`を`?`演算子で投げたかった(投げられなかった)

## 起こり得ない失敗を素早く握りつぶしたいという欲求

通常のプログラミングだとエラーハンドリングをする必要性があるところを, 競プロの場合「入力がフォーマットにしたがってさえいれば絶対にエラーが起こらないのでハンドリングをサボりたい」という要求が頻繁にある。

Rust の場合, その多くは`Option#unwrap()`および`Result#unwrap()`によって行われている。 これは成功していた場合値を取り出し, 失敗していた場合パニックする。

しかし, そのために 8 文字もタイプしなければいけないというのはちと面倒だ。他の言語だったら`!`みたいな演算子が用意されているのだが。

これに限らず Rust の Null ハンドリングは少々手間がかかる。`??`演算子は`Option#unwrap_or()`だし, `nullable?.hoge()`に至っては存在しないので`nullable.map(|x| x.hoge())`ないし`nullable.map(Nullable::hoge)`とする。

代わりに, といってはなんだが`?`演算子が存在する。 これは成功していた場合値を取り出し, 失敗していた場合はそれ自体を返しながらアーリーリターンする。 それ自体を返すので, 呼び出される関数自体も`Result`でなければならない。 これは Java の検査例外の`throws`と同等の機能を型機能のみで実現しつつ, 例外機構とほぼ変わらない書き心地を提供してくれるかなりの発明だ。

```java
int someFunction() throws SomeException {
  String str = someFailableFunction(); /* コレ自体が throws SomeException */
  /* ... */
  return i;
}
```

```rust
fn some_function() -> Result<i32, SomeError> {
  let str: String = some_failable_function()?; /* コレの返り値は Result<String, SomeError> */
  /* ... */
  Ok(i)
}
```

これを使えばハンドリングの省力化を実現できる。

## 詐欺じゃねえか

`?`演算子は`Result`に用意されていた`try!`マクロの演算子化である。 `main`の返り値を`Result<(), Box<dyn Error>>`とすると, たしかに`Result`は投げられるが`Option`は投げられない。

`?`演算子のオーバーロードのために用意されようとしている`Try`トレイトでは, `into_result`メソッドによって`Result`への変換ができることが要請されている。

しかし, それでも`Result<(), Box<dyn Error>>`の中で`Option`を投げることができない。 なぜかというと, `Option#into_result`によって得られるエラー型である`NoneError`は, `Error`トレイトを実装していないからである。 **詐欺じゃん!!**

この仕様については何度も議論がなされているようだ。 [ここ](https://internals.rust-lang.org/t/should-noneerror-implement-the-error-trait/6312)や[ここ](https://github.com/rust-lang/rust/issues/46871)など。 大抵の場合,

> そんなに`Result`に変換したいなら, なんの情報も持たない`NoneError`をそのまま使うよりも, `Optional#ok_or`でその問題に関するより詳細な情報を持たせるほうがより良い解決策でしょ。

みたいなことを言われてしまっている。 いやまあたしかにそれはそうなんだけど俺の目的からしたら`ok_or("")?`とか書くのは`unwrap()`って書いてるのと変わんねえって!

Haskell の型クラスと違い, Rust のトレイトは既存の型に既存のトレイトを実装することは許されていないので八方塞がりである。

## 独自のエラー型に変換しよう

`Box<dyn Error>`で横着することを諦めれば, 各種エラーと`NoneError`から変換できる独自のエラー型を定義して, それを`main`の返り値にすることで解決できなくはない。

もちろん, 発生しうるエラー型すべてに変換用のトレイトを実装しなければいけないのが面倒ではある。 しかし, そもそも正しいエラーハンドリングのあり方とはそうであるし, 競技中ではなく前もって用意できるテンプレートであるので許容範囲だろう。

ちなみに, 列挙せずにジェネリクスを使用して

```rust
impl From<NoneError> for MyError {
  fn from(_: NoneError) -> Self {
    MyError
  }
}

impl<T: Error> From<T> for MyError {
  fn from(_: T) -> Self {
    MyError
  }
}
```

みたいな横着した書き方はできない。なぜなら, たとえいま`NoneError`が`!Error`であっても将来的に`Error`を実装する可能性が否定できないため, このふたつの実装は衝突しているからである。 ~~そんなとこに文句言う暇あったら実装してくれや。~~ ~~トレイト境界を設けず`<T>`にしろって? ｱｰｱｰ聞こえない。~~

とはいえさすがにボイラープレート極まりないのでマクロを定義することにして, せっかくなのでもとのエラー情報も使いつつ実装したのが以下の感じである。

```rust
struct CompeError {
  source: Option<Box<dyn std::error::Error>>,
}

impl std::fmt::Debug for CompeError {
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    match &self.source {
      Some(x) => x.fmt(f),
      None => writeln!(f, "NoneError"),
    }
  }
}

impl std::fmt::Display for CompeError {
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    match &self.source {
      Some(x) => x.fmt(f),
      None => writeln!(f, "attempted to retrieve a value does not exist"),
    }
  }
}

impl std::error::Error for CompeError{}

macro_rules! ce {
  (std::option::NoneError) => {
    impl From<std::option::NoneError> for CompeError {
      fn from(_: std::option::NoneError) -> Self {
        CompeError{source: None}
      }
    }
  };
  ($t: ty) => {
    impl From<$t> for CompeError {
      fn from(e: $t) -> Self {
        CompeError{source: Some(Box::new(e))}
      }
    }
  };
}

ce!{std::option::NoneError}
ce!{core::num::ParseIntError}
/* あとはここに追記していく */
/* ... */

fn main() -> Result<(), CompeError> {
  let sout = std::io::stdout();
  let mut writer = std::io::BufWriter::new(sout.lock());

  input! {
  };
 
  let line = format!("{}\n", ans);
  writer.write(line.as_bytes())?;
  Ok(())
}
```

## おあとがよろしいようで

書いて動かせるのを確認したはいいものの, このコードは実際には競プロでは**使用できない**。 なぜなら`Try`トレイトそのものが Unstable なので Nightly でしか利用できないからだ(ドリフの笑い声)。 じゃあ`NoneError`が`!Error`だろうが`Error`だろうが関係ないわな。

ま, スニペットに`ok_or("■━⊂( ･∀･) 彡ガッ☆ (  д ) ° °")`でも登録しておきましょ。