The Rust Programming Languageを読み進める（1〜2章）

# はじめに
Rustのコードを、既存コードの横並びで書くことが多い。きちんとドキュメントを読んだことがないので、The Rust Programming Languageを頭から読み進めてみる。読みながら要点をまとめていった記事です。

# 1章：事始め
https://doc.rust-jp.rs/book-ja/ch01-00-getting-started.html
### Hello world
```rust
fn main() {
    println!("Hello, world!");
}
```
* Rustのインデントスタイルは4スペース
* `println!`は関数呼び出しではなく、マクロ呼び出し
    * ` let v = vec![1, 2, 3];` は、マクロ無しで書くと`v = Vec::new(); v.push(1); v.push(2); ...`と長くなる
* RustはAOT (Ahead-Of-Time) コンパイル言語のため、実行可能ファイルを配布可能
    * AOTコンパイル：実行前に機械語へ変換。実行時は速いが、ソースコードの状態で配布不可
    * JIT (Just in Time) コンパイル：実行時に機械語へ変換。コンパイル時に時間が掛かり最適化もされないが、ソースコードの状態で配布可能

### Cargo
```rust
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"

[dependencies]
```
* Cargoとは、ビルドシステム＆パッケージマネージャ
    * 依存ライブラリのダウンロードや、付随するビルドを実施
    * 設定ファイルは、TOML (Tom's Obvious Minimal Language) 形式
        * 設定ファイルのフォーマットの一種で、名の通りMinimal化されている
        * `[package]`：パッケージ情報の定義セクション
        * `[dependencies]`：依存するパッケージの定義セクション
* `Cargo.lock`はビルド時に生成され、ビルド時の全ライブラリのバージョンが記録
* 主要コマンド
    * `cargo new`：プロジェクトを作成
    * `cargo build`：プロジェクトをビルド
    * `cargo run`:プロジェクトのビルドと実行を1ステップで実施
    * `cargo check`：バイナリ生成せずプロジェクトをビルド。エラー有無確認などに使う

# 2章：数当てゲームのプログラミング
https://doc.rust-jp.rs/book-ja/ch02-00-guessing-game-tutorial.html

### 数を入力するだけの処理
```rust
use std::io;

fn main() {
    println!("Guess the number!"); 
    println!("Please input your guess."); 
    let mut guess = String::new();
    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");
    println!("You guessed: {}", guess); 
}
```
```
$ cargo run
   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 6.44s
     Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
6
You guessed: 6
```
以下、各行の処理に注目する。
```rust
use std::io;
```
* Rustには多様なライブラリが存在するが、`use`を取り込むことで取り込める
* ただし量が多くなることもあるため、Preludeという仕組みも提供している
    * Rustのライブラリをリストとして内包し、使いたいトレイトにアクセスしやすくなる
    * 例：`use std::io::prelude::*;`
```rust
    let mut guess = String::new();
```
* `let`：変数定義（変数の束縛）
* `mut`：Rustの変数がデフォでimmutable（不変）のため、mutable（可変）として定義
* `::`：関連関数。`String`に関連付けられた関数`new`を呼び出し、戻り値を`guess`に束縛
```rust
    io::stdin()
        .read_line(&mut guess)
```
* `io::stdin()`：標準入力のためのインスタンスを返却
* `read_line(&mut guess)`：ユーザからの入力を得て、内容を`guess`に格納
    * `&`は引数が参照であることを表し、参照自体が可変。メモリに複数書き込みをせずとも、他のところから同じデータにアクセス可能
    * Rustは変数だけではなく、参照もデフォルトで不変
* `read_line`：Result型（列挙型）の`Ok`または`Err`を返す
```rust
        .expect("Failed to read line");
```
* `expect`：ReturnされたResult型の結果が`Ok`の場合に値を返し、`Err`の場合はプログラムが終了
* `expect`無しでは、返ってきた`Result`が使われていないことが警告される

### 乱数を生成・比較するロジックを加える
```rust
use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");
    
    let secret_number = rand::thread_rng().gen_range(1..101);
    
    loop {
        println!("Please input your guess.");
        println!("The secret number is: {}", secret_number);
        
        let mut guess = String::new();
        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");
    
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };
        println!("You guessed: {}", guess);
        
        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}
```
```
$ cargo run
   Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.43s
     Running `target/debug/guessing_game`
Guess the number!
The secret number is: 58
Please input your guess.
  76
You guessed: 76
Too big!
```
以下、各行の処理に注目する。
```rust
use rand::Rng;
```
* `rand`クレートを使うために、tomlファイルに`rand = "0.8.3"`を追加
    * `^0.8.3`の省略記法であり、0.8.3以上0.9.0未満のバージョンを表す
* Cargoはセマンティックバージョニングに基づいて取得するパッケージを決定 (X.Y.Z)
    * X：後方互換のないメジャーバージョン
    * Y：後方互換のあるマイナーバージョン
    * Z：後方互換のあるパッチパージョン
* 常に決まったクレートを使いたければ、`Cargo.lock`をGit管理にする
* Cargoはリストアップされているクレートをチェックし、未取得対象があればダウンロード。取得済のクレートは、再度ダウンロードすることがない
    * 参照先はcretes.io (https://crates.io/)
    * `cargo update`でバージョンアップデートし、lockファイルに記録
```rust
    let secret_number = rand::thread_rng().gen_range(1..101);
```
* `rand::thread_rng`：乱数生成器の初期化
* `gen_range(low, high)`：lowからhigh-1の範囲内で乱数を生成
```rust
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };
```
* 入力した値の`guess`はString型、一方で`secret_number`は数値型であるため型不一致。そこで、`String`が用意する`parse`で数値型に変換
* `parse`は`Result`を返すため、`match`の`Err`時（文字列の入力）に再入力させている
    * `_`はすべての値にマッチ
* `trim()`はEnter入力時に改行されるため、`\n`を消すために使用
* `guess`の再代入部分はシャドーイングと呼び、同じスコープ内の変数が再宣言可能
  * `let mut`を宣言して値を変えるのとは性質が異なり、**使用する型自体を変更可能**。よって、値は同じだけれど、異なる方として定義したい場合に使用
* どの型としてシャドーイングしたいかを宣言するため、`u32`は明示的に必要
    * `secret_number`も`u32`であるべきと推論できる

```rust
    match guess.cmp(&secret_number) {
        Ordering::Less => println!("Too small!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal => println!("You win!"),
    }
```
* 入力値`guess`と、乱数で生成した`secret_number`を比較し、`Ordering`の列挙子を返却
* `match`は式がパターンと一致するか判定
    * `パターン => 式`をアームと呼ぶ
    * 取り得る値は全て網羅する必要があり、必要に応じて`_`を使う
* `Ordering`は`Less`, `Greater`, `Equal`を持つ列挙型