LoginSignup
6
3

More than 5 years have passed since last update.

RustでEitherを実装する(している)

Posted at

きっかけ

最近、Rustを始めて標準でEitherがないのは不便と思ったので、実装しています。
元々、Scalaをやっていたので実装はScalaに合わせています。

困っていること

flatMapの実装

ScalaだとasInstanceOfを使っていて以下のような型変換が可能ですが、

import scala.util.Right

val r = Right("right") // scala.util.Right[Nothing,String]
r.asInstanceOf[Either[Nothing, Int]] // Either[Nothing,Int]

Rustだとこんな便利関数は見つけられませんでした。
そこで、これを再現する方法を以下の2つ思いつきましたが、結局transmuteを使う事で実現したい事の半分は出来ました。
(ジェネリクス使った際のキャストのベストプラクティスわかる方いたら教えて欲しいです)

  • transmute
  • libc::mallocで頑張る

transmuteはコンパイル時にサイズがわかっていないといけない(?)のでBoxに包んで誤魔化す事でコンパイルは出来ました。

問題発生

コンパイルは通り、実行してみると落ちるという現象が起きました。
落ちる原因は型のサイズ違いによりメモリ違反?かなんかが起きていると考えています。
(バイナリのデバック方法をよくわかっていない)
実行時に落ちるのは使い物にならないので、これを何とかしたいけど現状方法が何も思いついていません。
以下、再現コードです。

extern crate scala;

use std::num::ParseIntError;
use scala::util::Either;

fn main() {
    let result = f("a1000")
        .flat_map(Box::new(|n|f1(n)));
    println!("{:?}", result); //Left(ParseIntError { kind: InvalidDigit })

    let result = f("a1000")
        .flat_map(Box::new(|n|e1(n)));
    //printlnしたら落ちる
    //println!("{:?}", result);
}

fn f(s: &str) -> Either<ParseIntError, u64> {
    Either::parse_result(s.parse())
}

fn f1(n: u64) -> Either<ParseIntError, u8> {
    Either::parse_result(format!("{}", n).parse())
}

fn e1(n: u64) -> Either<String, String> {
    if n == 1000 {
        Either::Right("n is 1000".to_string())
    } else {
        Either::Left("n is not 1000".to_string())
    }
}
# cargo run
   Compiling scala v0.1.0 (file:///root/scala)
    Finished dev [unoptimized + debuginfo] target(s) in 1.25 secs
     Running `target/debug/scala`
Left(ParseIntError { kind: InvalidDigit })
Illegal instruction (core dumped)

今後実装したい事

for式

簡単にですが、以下のように使えるように実装してみました。
e_forという名前なのはforが使えなかったからです。
変数束縛とかちゃんと実装していきたいです。

let result = e_for!{
    _ <- f("1100")
    _ <- f1()
    _ <- f2()
};

他のライブラリ

Scalaの標準ライブラリは書きやすいのが多いので実装していきたい。

6
3
13

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3