1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rustの基本的な関数

Posted at

はじめに

Rustの基本的な関数3つについて、RPN計算機プログラムを見ながら解釈していく。

リファレンス

実践Rust入門 言語仕様から開発手法まで
URL(amazon): https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5Rust%E5%85%A5%E9%96%80-%E8%A8%80%E8%AA%9E%E4%BB%95%E6%A7%98%E3%81%8B%E3%82%89%E9%96%8B%E7%99%BA%E6%89%8B%E6%B3%95%E3%81%BE%E3%81%A7-%CE%BAeen/dp/4297105594
URL(楽天): https://books.rakuten.co.jp/rb/15856840/

著者本人のブログ
κeenのHappy Hacκing Blog | Lispエイリアンの狂想曲

RPNについて

RPNとは__"Reverse Polish Notation"の略で、日本では"逆ポーランド記法"__と呼ばれる。(基本情報にでてくるらしい。)
僕自身は、「かっこ」のイメージでとらえている。

例えば、

11 + 22
は、

11 22 +
と表記する。+の値がべ手の四則計算記号になっても同様である。
少し応用。

11 22 * 33 +
はいつもどうりに直すと、

11 * 22 + 33
となる。
もとの式をかっこを付けてわかりやすくしてみると

{(11 22) * 33 }+
という風にみえる。自分なりの解釈の仕方でいいと思う。

これを基にすると、

11*(22+33)
という普通式は、

11 22 33 + * ⇐ { 11 ( 22 33 ) + } *
となる。

RPN計算機プログラム ソースコード

from https://github.com/ghmagazine/rustbook/blob/master/ch02/rpn/src/main.rs
上記記載のコードは、日本語による説明あり。

file name == main_function

fn main() {
    let exp = "13.3 6.3 3.9 * + 3.7 2.8 / 9.1 * -";
    let ans = rpn(exp);
    debug_assert_eq!("25.8450", format!("{:.4}", ans));
    println!("{} = {:.4}", exp, ans);
}

fn rpn(exp: &str) -> f64 {
    let mut stack = Vec::new();
    for token in exp.split_whitespace() {
        if let Ok(num) = token.parse::<f64>() {
            stack.push(num);
        } else {
            match token {
                "+" => apply2(&mut stack, |x, y| x + y),
                "-" => apply2(&mut stack, |x, y| x - y),
                "*" => apply2(&mut stack, |x, y| x * y),
                "/" => apply2(&mut stack, |x, y| x / y),

                _ => panic!("Unknown operator: {}", token),
            }
        }
    }
    stack.pop().expect("Stack underflow")
}

fn apply2<F>(stack: &mut Vec<f64>, fun: F)
where
    F: Fn(f64, f64) -> f64,
{
    if let (Some(y), Some(x)) = (stack.pop(), stack.pop()) {
        let z = fun(x, y);
        stack.push(z);
    } else {
        panic!("Stack underflow");
    }
}
}

ソースコード解釈(概要)

fn main()

で、メイン関数が定義される。
その中身を今回は

13.3 6.3 3.9 * + 3.7 2.8 / 9.1 * -
という式の内容を計算する。
これの答えは、

25.8450
となるはずである。

__let__により新しい変数の用意をする。すなわち、値に新しい名前を付ける。

ここで、__main関数のみで実行してみる__と、

error[E0425]: cannot find function `rpn` in this scope
 --> main_function.rs:3:15
  |
3 |     let ans = rpn(exp);
  |               ^^^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.

と出てくる。「rpnに関する定義がない。」となるので、その定義となる__rpn関数__が必要となる。
なので、

fn rpn()

その中身が以下のようになっている。

fn rpn(exp: &str) -> f64 {
    let mut stack = Vec::new();
    for token in exp.split_whitespace() {
        if let Ok(num) = token.parse::<f64>() {
            stack.push(num);
        } else {
            match token {
                "+" => apply2(&mut stack, |x, y| x + y),
                "-" => apply2(&mut stack, |x, y| x - y),
                "*" => apply2(&mut stack, |x, y| x * y),
                "/" => apply2(&mut stack, |x, y| x / y),

                _ => panic!("Unknown operator: {}", token),
            }
        }
    }
    stack.pop().expect("Stack underflow")
}

という、関数の塊ができる。f64型(64ビット浮動小数点数)で定義しているので、もっと多くの2進数計算となる場合、ビット数は増やさなければならない。
apply2
というものに関して、定義されているものはソースコードの塊で一番下の__apply2関数__によって定義される。
よって

fn apply2()

fn apply2<F>(stack: &mut Vec<f64>, fun: F)
where
    F: Fn(f64, f64) -> f64,
{
    if let (Some(y), Some(x)) = (stack.pop(), stack.pop()) {
        let z = fun(x, y);
        stack.push(z);
    } else {
        panic!("Stack underflow");
    }
}
}

というように定義されている。

中身に関しては、github(URL上記記載)での説明を見ればわかる。
これで、大枠のことがわかる。
構造自体は、C/C++に似ているので、非常にわからいやすい。

最後に

rustに関する記事は、様々なものを調べていながら、Errorを発生させてみながら、学んでみる。Error内容にも強くなっていきたい。または、もらいたい。

1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?