rust初めてみた

Cって取得に人生賭ける必要があるってどっかに書いてあった。
だからrustに乗り換えた。

...寿命10年延ばしたくなった。

:::note warn
注意：　この記事は重要なことを説明していません。　ただ当然のことをつらつら書いています。
:::

## 0. 関数
`fn`キーワードをつければ関数になります。
```rust
// 何も値を返さない関数
fn test() {
    // !が付くとマクロになる。
    // マクロは、コンパイラーが動的に関数を作ってくれる。
    println!("Hello_world!");
}
// 値を返す関数
fn pi() -> f64 {
    // let で xという変数 に 数値(3.14...) を束縛した
    let x = 3.141592;
    // ;省略は、returnの糖衣構文
    x
}
// 値を代入し、別の値で返す関数
fn circumference(x: f64) -> f64 {
    // return で書いても良い
    return {
        // ブロックに直して計算させることもできる。
        let y = x * 2.0;
        y * pi()
    };
}

// main関数、すべてのプログラムはここから始まる
fn main() {
    let x = 5.0;
    test();
    println!("半径{}の円周の長さは{}です。", x, circumference(x));
}
```
```
Hello_world!
半径5の円周の長さは31.41592です。
```
## 1. 構造体
いうまでもなく構造体です。　
```rust
struct ExampleStructure {
    x: i32,
    y: f64,
}
// こちらの構造体は次の項で使います
// _は、予約するといって、使わないけど将来的に
// 使うだろうという変数や構造体、関数の名前の
// 先頭につけますね。
// 使うときに除去しましょう。
struct _ExampleProfileCard {
    name: String,
    age: i32,
    //sex: Gender,
}

fn main() {
    let x = ExampleStructure{ x:33, y:4.0 };
    println!("{}-{}",x.x,x.y);
}
```
```
33-4
```

## 2.列挙型
どちらか一つ... って時に使いますね。
```rust
enum Gender {
  Man,
  Woman,
}
```
```diff
- struct _ExampleProfileCard {
+ struct ExampleProfileCard {
```
```rust
fn main() {
    let profile = ExampleProfileCard {
        name: String::from("Nick"),
        age: 25,
        sex: Gender::Man,
    };
    println!("hello!");
    println!("My name is {},", profile.name);
    println!("my age is {},", profile.age);
    // matchというのはswitchに近い動作をしてくれます。
    match profile.sex {
        // 男なら
        Gender::Man => {
            println!("my gender is male.");
        },
        // 女なら
        Gender::Woman => {
            println!("my gender is female.");
        },
    }
    println!("nice to meet you.");
}
```
```
hello!
My name is Nick,
my age is 25,
my gender is male.
nice to meet you.
```
```diff
-        name: String::from("Nick"),
-        age: 25,
-        sex: Gender::Man,
+        name: String::from("emily"),
+        age: 18,
+        sex: Gender::Woman,
```
```
hello!
My name is emily,
my age is 18,
my gender is female.
nice to meet you.
```
matchが機能していて、かつ自己紹介がしっかりできてますねぇ。

# 2.5 データ入り列挙型
列挙型にデータを入れる？そんな馬鹿な。
ってことができます。　

```rust
enum CentralLeague {
    giants,
    takult,
    dena,
    dragons,
    hanshin334,
    hirosima,
}

enum PacificLeague {
    nippon_ham,
    rakuten,
    lions,
    lotte,
    orix,
    sofban,
}

enum BaseballTeams {
    ce_league(CentralLeague),
    pa_league(PacificLeague),
    high_school(String),
    other(String),
}
```

これは日本の主要野球チームを列挙型に収めたものです。
また、主要リーグを分けて、リーグの中にチーム名を収めています。
なお、高校野球チームは列挙しきれないので、文字列型にしています。

```rust
// implは後で解説するね
impl BaseballTeams {
    // selfはpythonと意味合いは同じ
    // インスタンス化したBaseballTeams列挙型
    // が入っていると思ってちょ
    fn get_name_japanese(&self) -> String {
        match &self {
            // セリーグの時
            // name は インスタンス化された CentralLeague列挙型
            // が入ります。
            BaseballTeams::ce_league(name) => match name {
                CentralLeague::dena => String::from("セリーグの横浜dena"),
                CentralLeague::dragons => String::from("セリーグの中日ドラゴンズ"),
                CentralLeague::giants => String::from("セリーグの巨人"),
                CentralLeague::hanshin334 => String::from("セリーグの阪神"),
                CentralLeague::hirosima => String::from("セリーグの広島"),
                CentralLeague::takult => String::from("セリーグのヤクルト"),
            },
            // パリーグの時
            // 上に同じく
            BaseballTeams::pa_league(name) => match name {
                PacificLeague::lions => String::from("パリーグの西武"),
                PacificLeague::lotte => String::from("パリーグのロッテ"),
                PacificLeague::nippon_ham => String::from("パリーグの日本ハム"),
                PacificLeague::orix => String::from("パリーグのオリックス"),
                PacificLeague::rakuten => String::from("パリーグの楽天"),
                PacificLeague::sofban => String::from("パリーグのソフバン"),
            },
            // 高校野球
            // nameには文字列が入っています。
            // format! は、println!を文字列として返す
            BaseballTeams::high_school(name) => String::from(format!("高校野球チームの{}", name)),
            // otherは紹介しても無駄だから"とあるチーム"とするよ
            // _は、「その値は使わない」という意味を持っているよ
            BaseballTeams::other(_) => String::from("とあるチーム"),
        }
    }
}
```

コメントでもうっすら書きましたが、例えば日本語文字列でデータを取り出したいとします。
そうすると（ちょっと無駄な構造ではあるものの）こういう形の関数がぱっと浮かぶはずです。
この関数は、BaseballTeams型のデータが取り入れられたとき、適切な文字列に直して出力してくれます。

## 3. 関連した関数を取り付ける
関連した関数...つまり、構造体や列挙型に**関連した**関数を取り付けるというものです。
実は先ほどの例がそれで、`impl`文で関数を関連付けることができます。

この関数は次のように使われます。

```rust
struct ScoreBoard {
    home: BaseballTeams,
    home_point: i32,
    away: BaseballTeams,
    away_point: i32,
}

fn news(score: &ScoreBoard) {
    let home = &score.home;
    let away = &score.away;
    println!("野球の最新情報です。");
    println!(
        "{}対{}の試合がありました",
        home.get_name_japanese(),
        away.get_name_japanese(),
    );
    print!("試合結果は、{}-{}で", score.home_point, score.away_point);

    if score.home_point == score.away_point {
        println!("同点という結果になりました。");
    } else if score.home_point > score.away_point {
        println!("{}の勝利でした。", home.get_name_japanese());
    } else {
        println!("{}の勝利でした。", away.get_name_japanese());
    }
}

fn main() {
    let march_24_escon = ScoreBoard {
        home: BaseballTeams::pa_league(PacificLeague::nippon_ham),
        home_point: 2,
        away: BaseballTeams::ce_league(CentralLeague::dena),
        away_point: 3,
    };

    news(&march_24_escon);
}
```

まず、scoreboardという構造体を定義しちゃいました。　簡単な話、homeチームとawayチーム、そしてそれぞれの点数を記録する構造体です。

次に、関数newsを定義しました。　このnewsは、例えばこのように出力します。
> 野球の最新情報です。
> パリーグの日本ハム対セリーグの横浜denaの試合がありました
> 試合結果は、2-3でセリーグの横浜denaの勝利でした。
要するに、野球のニュース記事として出力してくれるわけです。

scoreboardのhomeとawayには、`BaseballTeams`列挙型がそれぞれ含まれています。
`BaseballTeams`列挙型には`impl`で`get_name_japanese`関数を関連付けています。

そしてそれを呼び出す方法は
`home.get_name_japanese()`
`away.get_name_japanese()`

これってさ...メソッドのことでしょ？

そうです、メソッドです。

ここからは独自研究の含まれる説明ですので、隠しておきます。
<details><summary>私なりの解釈</summary>

メソッドなんですが、ここで一つ、ほぼすべてのオブジェクト指向言語で共通の話をします。

メソッド... というのは、インスタンス化されても変化しないデータの一つです。
それは、static(静的)変数（関数）も同じです。
実際、「インスタンス化された」というのは、
構造体・列挙体・クラスなどに値が入れられた（束縛された）状態を指します。

メモリ的に見てみましょう。
変数の値というのはすべての型で同じなわけがありません。
よく見るcharは1byte(8bit)、intは環境などによって32bit(4byte)や64bit(8byte)、
stringに至ってはcharの配列になります。

ここで、配列型が、「なぜ別々の型を同時に入れることができないか」というのを考えてみましょう。
配列型はどんなに長くても「型は変わらない」という保証があるのです。
もし、型がバラバラな配列があったらどうでしょうか。

4bitの型と8bitの型があると仮定して話していきます。

4bitの型にも8bitの型にもそれぞれ10という数字を入れてみましょう

4bit: 1010
8bit: 0000 1010

4bit配列を定義してみます。
先ほど定義した4bitの変数を、4つ並べて入れます。
1010 1010 1010 1010
c風に書くとこうなります
```
4bit[4] x;
x[0] = 1010;
x[1] = 1010;
x[2] = 1010;
x[3] = 1010;
```

では、この配列を、8bit配列としてみたらどうなるでしょうか。
x[0] = 10101010
x[1] = 10101010
x[2] = ?????

x[2]は定義されていません！　これは実は恐ろしいことです。
なぜなら配列外のアクセス、つまり「不正アクセス」になるからです。
しかも、8bitで得た値は10ではなく、170になってしまいました！

これで、型の重要性というの理解できたはずです。
この型システムというのは、値の長さ、値の形式を記録し、
その用途に合った使用方法ができるように定義するものなのです。

動的型割り当てなどと呼ばれている言語はもう少し複雑です。　ここでは割愛します。

配列では同じ型のデータを代入してましたが、構造体では複数の型のデータを代入したいときに使います。
そのため、構造体はあらかじめ「どこに何が含まれているのか」という情報を型として記録しておく必要があるのです。

構造体というのはオリジナルな型の一つです。　そのプログラム特有の型であり、
標準ではない型の一つなのです。

インスタンス化というのは、ある型の変数に値を代入した　ただそれだけのことなのです。

関数はどうでしょうか。　関数型の変数に、関数を代入した　なんてことがない限り、
関数というのは不変です。　実際関数型をインスタンス化するときに代入することはありますか？

関数を代入した場合、それはコールバック関数などと呼ばれる可能性が高いです。
今回の話題には関係ないので割愛します。

関数というのは代入することはありません。　
データとしてみてみましょう。　構造体というオリジナルな型の変数に代入した値それぞれに、関数のデータを入れる必要はあるでしょうか。

無論ありません。　つまり、クラスとして一緒に定義する「メソッド」というのは、データ上で見れば別のところに定義されているのです。
implはそれをわかりやすく表現してくれています。

impl文は構造体に関数を「関連付けている」といいましたが、その構造体をもっと便利にアクセスできるように、
専用の関数を関連付けながら定義している、ただそれだけなのです。

そのため、関数の呼び出し方はこうなります。
```rust
hogehoge.fugafuga()

// もしfugafuga関数が定義されていない場合、次の関数呼び出しは
// 無効となる。
fugafuga() // エラー
```
</details>

関連付けた関数は、構造体インスタンスか、構造体の型をデータとしてみて実行することができます。
```rust
home.get_name_japanese()
```
先ほどmain関数で束縛したインスタンスを実行すると、こういう結果を出します。
```
セリーグの横浜dena
```

宣言部を見てみましょう。
```rust
fn get_name_japanese(&self) -> String {
```
ここで重要視されたいのはこの文です。
self これはpythonで見る構文の一つです。　selfは多言語のthisに近い働きをします。

# 現時点でのまとめ
そのうちこの記事更新します。

rustって型付きpythonだよね。　そうとしか思えん。
独自研究の部分は本当に自己解釈で書いてるし、何なら関係ない解説も含まれているので
見なくていいです。てか見るな（じゃあ書くな）

それ以外は大体日本語ドキュメント（？）を見て書きました。
優秀すぎる

[The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/title-page.html)

環境整えるのが大変な方に朗報です。

[Playground](https://play.rust-lang.org/)