kdnakt blog

hello there.

Rust dojo第66回を開催した

第66回です。前回はこちら。

kdnakt.hatenablog.com

[第66回の様子]

2023/02/08に第66回を開催した。

内容としてはRust By Example 日本語版19. 標準ライブラリの型の「19.5. Result」に取り組んだ(「19.5.1. ?」には進めず)。
参加者は自分を入れて5人。

メンバが集まるまで5分ほど待って、「19.5. Result」を終わって次に進めるほど時間がなかったので、3分ほどはやく終わったので、実質20分ほどの勉強会だった。
リモートのミーティングの場合、トイレ休憩などが考慮されず前後が詰まりがちなので、これくらいでちょうどいいかも。

[学んだこと]

  • 19.5. Result
  • 先週はOptionがテーマだった。これは値がないことは示せるが、その原因は示せないのでちょっと困る。そういう時はResult型を使うと、エラーを示すことができる。
  • ちなみにOptionResultenumの一種。
    • OptionSomeNoneを取る
    • ResultOkErrを取る
  • というわけで実コードを見ていく
  • まずはエラーとそのエラーをもつResultに対するエイリアスを定義する
mod checked {
    // 数学的な「エラー」
    #[derive(Debug)]
    pub enum MathError {
        DivisionByZero,
        NonPositiveLogarithm,
        NegativeSquareRoot,
    }

   pub type MathResult = Result<f64, MathError>;
}
  • つぎにMathResult型を返す関数を実装する
mod checked {
    // MathErrorとMathResultの定義は省略
    pub fn div(x: f64, y: f64) -> MathResult {
        if y == 0.0 {
            Err(MathError::DivisionByZero)
        } else {
            Ok(x / y)
        }
    }

    pub fn sqrt(x: f64) -> MathResult {
        if x < 0.0 {
            Err(MathError::NegativeSquareRoot)
        } else {
            Ok(x.sqrt())
        }
    }

    pub fn ln(x: f64) -> MathResult {
        if x <= 0.0 {
            Err(MathError::NonPositiveLogarithm)
        } else {
            Ok(x.ln())
        }
    }
}
  • 上記のcheckedモジュールを利用して計算すると以下のようになる
// `op(x, y)` === `sqrt(ln(x / y))`
fn op(x: f64, y: f64) -> f64 {
    match checked::div(x, y) {
        Err(why) => panic!("{:?}", why),
        Ok(ratio) => match checked::ln(ratio) {
            Err(why) => panic!("{:?}", why),
            Ok(ln) => match checked::sqrt(ln) {
                Err(why) => panic!("{:?}", why),
                Ok(sqrt) => sqrt,
            },
        },
    }
}

fn main() {
    println!("{}", op(1.0, 10.0));
    // まず割り算:1.0 / 10.0 = 0.1
    // つぎに自然対数をとる:log(0.1) = -2.3025850929940455
    // 負の数の平方根は計算できないので次のようにパニックしてしまう
    // thread 'main' panicked at 'NegativeSquareRoot', src/main.rs:53:29
}
  • 適当に数字を入れ替えてみると、パニックせずにプログラムが終了した。
fn main() {
    println!("{}", op(10.0, 1.0));
    // div(10, 1) = 10.0
    // log(10) = 2.302585092994046
    // √2.302585092994046 = 1.5174271293851465
}

[まとめ]

モブプログラミングスタイルでRust dojoを開催した。

対数って言われてパッとイメージがわかなかった。高校数学勉強し直さないとな...

今週のプルリクエストはそのうち追記予定...。

[2023/02/18追記]

github.com