The Rust Programming Languageを読み進める（7章）

# はじめに

The Rust Programming Languageを頭から読み進めてみる。読みながら要点をまとめていった記事です。

* [The Rust Programming Languageを読み進める（1〜2章）](https://qiita.com/yktooo/items/df17496b38b1b5c49aba)
* [The Rust Programming Languageを読み進める（3章）](https://qiita.com/yktooo/items/481d49f248cb9947af81)
* [The Rust Programming Languageを読み進める（4章）](https://qiita.com/yktooo/items/e0d502867e16ce91923a)
* [The Rust Programming Languageを読み進める（5章）](https://qiita.com/yktooo/items/8e5890c235ed9f5a6b4b)
* [The Rust Programming Languageを読み進める（6章）](https://qiita.com/yktooo/items/a0808a46043182ab6f84)

# 7章：肥大化していくプロジェクトをパッケージ、クレート、モジュールを利用して管理する
Cargoの構成は下記の画像のようになっている：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3751499/19463f3d-a9b9-b534-4fca-593009ac9fd3.png)
Cargoプロジェクトの構造 (Quoted from "Practical System Programming for Rust Developers," [Link](https://subscription.packtpub.com/book/programming/9781800560963/2/ch02lvl1sec05/introducing-cargo-and-project-structures))

* パッケージ
* クレート（木枠）
    * `Cargo.toml`に定義されているビルドの単位
    * 実行バイナリとライブラリの2つに分かれる
* モジュール
    * モジュールはクレートの要素に対して階層構造を持たせた仕組み
* パス
    * モジュールの場所を示すための名前

## 7.1章：パッケージとクレート
https://doc.rust-jp.rs/book-ja/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html
* パッケージは、ある機能群を提供する1つ以上のクレート
* パッケージは、各クレートをどの様にビルドするかを定義した`Cargo.toml`を持つ
* パッケージを作るコマンドと、作った後のツリーは下記の通り

```
$ cargo new my-project
```
```
.
└── my-project
    ├── Cargo.toml
    └── src
        └── main.rs
```
```toml
[package]
name = "my-project"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
```
* `my-project`という名前の、バイナリクレートを持っている状態
    * `src/main.rs`と`src/lib.rs`があれば、クレートは2つになる
    * 実行バイナリ
        * エントリポイントを持つ
        * `main.rs`がクレートルート
    * ライブラリクレート
        * エントリポイントを持たない
        * `lib.rs`がクレートルート（上記ルートでは定義なし）

## 7.2章：モジュールを定義して、スコープとプライバシーを制御
https://doc.rust-jp.rs/book-ja/ch07-02-defining-modules-to-control-scope-and-privacy.html

* モジュールはクレートの要素に対して階層構造を持たせた仕組み
* コードをグループ化することで、可読性と再利用性の向上に貢献
* 以下はモジュールの定義とモジュールツリーの例
    * `mod`を使って定義し、本体を`{}`で囲む
    * `pub mod xxx`や`pub fn xxx`のように書くことで、public/privateの制御も可能

```rust
mod front_of_house {
    mod hosting {
        fn add_to_waitlist() {}
        fn seat_at_table() {}
    }

    mod serving {
        fn take_order() {}
        fn serve_order() {}
        fn take_payment() {}
    }
}
```
```
crate
 └── front_of_house
     ├── hosting
     │   ├── add_to_waitlist
     │   └── seat_at_table
     └── serving
         ├── take_order
         ├── serve_order
         └── take_payment
```

## 7.3章：モジュールツリーの要素を示すためのパス
https://doc.rust-jp.rs/book-ja/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html

### 絶対パスと相対パス
```rust
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {
            println!("Hi!");
        }
    }
}

pub fn eat_at_restaurant() {
    // 絶対パス
    crate::front_of_house::hosting::add_to_waitlist();
    // 相対パス
    front_of_house::hosting::add_to_waitlist();
}

fn main(){
    eat_at_restaurant();
}
```
```
Hi!
Hi!
```
* 絶対パスは、`crete`（ルート）から`::`でパスを繋いでいく
* 相対パスは、今のモジュールから`::`でパスを綱で行く
* Rustは基本的な要素が**デフォルトでPrivate**
    * なので、公開する場合は`pub`キーワードを使う

### 相対パスをsuperで始める
```rust
fn serve_order() {}

pub mod back_of_house {
    pub fn fix_incorrect_order() {
        cook_order();
        super::serve_order();
        println!("fix incorrect order");
    }

    fn cook_order() {
        println!("cook order");
    }
}

fn main(){
    back_of_house::fix_incorrect_order();
}
```
```
cook order
fix incorrect order
```
* `親モジュールから始まる相対パスは、`super`をつけることで実装できる
* `main()`では、次の通り`fix_incorrect_order()`が呼び出される
    1. 内部の関数の`cook_order`が呼ばれる
    2. `super`、つまり`back_of_hosue`の親モジュールである`crate`を見つけ、`serve_order`を探して見つけて呼ぶ
    3. print文が呼ばれる

### 構造体とenumを公開する
```rust
mod back_of_house {
    #[derive(Debug)]
    pub struct Breakfast {
        pub toast: String,
        seasonal_fruit: String,
    }

    #[derive(Debug)]
    pub enum Appetizer {
        Soup,
        Salad,
    }

    impl Breakfast {
        pub fn summer(toast: &str) -> Breakfast {
            Breakfast {
                toast: String::from(toast),
                seasonal_fruit: String::from("peaches"),
            }
        }
    }
}

pub fn eat_at_restaurant() {
    let mut meal = back_of_house::Breakfast::summer("Rye");
    println!("{:?}", meal);

    meal.toast = String::from("Wheat");
    println!("{:?}", meal);

    // pubを付けない限りエラー
    // println!("{:?}", meal.seasonal_fruit);
    // meal.seasonal_fruit = String::from("blueberries");

    println!("{:?}", back_of_house::Appetizer::Soup);
    println!("{:?}", back_of_house::Appetizer::Salad);
}

fn main() {
    eat_at_restaurant();
}
```
```
Breakfast { toast: "Rye", seasonal_fruit: "peaches" }
Breakfast { toast: "Wheat", seasonal_fruit: "peaches" }
Soup
Salad
```
* 構造体`Breakfast`は`pub`を付けることで公開できるが、フィールドは非公開のままなので、**フィールドごとに公開の有無を決めることが出来る**
* 公開されなかったフィールドは、アクセスすることや書き換えることは不可
* `enum`は`pub`で公開すると、フィールドは公開になる
    * 背景としては、1つ1つのバリアントに`pub`をつけるのが面倒だし、公開されていない方が不変

## 7.4章：useキーワードでパスをスコープに持ち込む
https://doc.rust-jp.rs/book-ja/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html

### useを使う
```rust
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {
            println!("Hi!");
        }
    }
}

use crate::front_of_house::hosting;
use std::collections::HashMap;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}

fn main() {
    eat_at_restaurant();

    let mut map = HashMap::new();
    map.insert(1, 2);
    println!("{:?}", map);
}
```
```
Hi!
Hi!
Hi!
{1: 2}
```
* 7.3章では`front_of_house::hosting::add_to_waitlist();`と呼び出しが長かったが、`use`を使うとシンボリックリンクを定義でき、`hosting::add_to_waitlist();`だけで済む
* `use crate::front_of_house::hosting::add_to_waitlist;`と定義して、`add_to_waitlist();`と**端的に呼び出すのは慣例ではない**。なぜなら、どこのモジュールの話なのかが分からなくなるため
* `pub use crate::front_of_house::hosting;`と`pub use`の定義により**外部のコードからアクセスが可能**
* `HashMap`構造体をスコープに定義しているが、この書き方が慣例

### 新しい名前をasキーワードで与える
```rust
use std::fmt::Result;
use std::io::Result as IoResult;

fn function1() -> Result {
    println!("This is function1!");
    Ok(())
}

fn function2() -> IoResult<()> {
    println!("This is function2!");
    Ok(())
}

fn main() {
    println!("Hello world!");

    if let Err(e) = function1() {
        println!("Error in function1: {:?}", e);
    }

    if let Err(e) = function2() {
        println!("Error in function2: {:?}", e);
    }
}
```
```
Hello world!
This is function1!
This is function2!
```
* 同じ型を複数使いたい時は、親モジュールを定義する必要がある
    * `fn function1() -> Result`と`fn function2() -> Result`だと区別ができない
    * なので`fn function1() -> fmt::Result`と`fn function2() -> io::Result<()>`のように定義する
* 上記サンプルのように、`as`と新しいローカル名（エイリアス）を指定すれば名前の衝突を避けられる

### 外部のパッケージを使う
```rust
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..101);
    println!("rand number: {}", secret_number);
}
```
```
rand number: 54
```
* `Cargo.toml`に追加したクレートはダウンロードされて使用可能になる
* サンプルの例は、クレート`rand`の`Rng`トレイトをスコープに持ち込み、`rand::thread_rng()`関数を呼び出している状態

### useのネスト
```rust
use std::{cmp::Ordering, io};
use std::io::{self, Write};
```
* `use`を使う時に、`use std::cmp::Ordering;`, `use std::io;`と書いていくと長くなる
* 中括弧でネストすることで、宣言文を削減できる

### glob演算子
```rust
use std::collections::*;
```
全ての公開要素をスコープに持ち込みたい時は、glo演算子`*`を続けて書く

## 7.5章：モジュールを複数のファイルに分割する
https://doc.rust-jp.rs/book-ja/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html

```rust
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}
```
上記コードについて、下記のように複数のファイルに分割可能
```rust
mod front_of_house;

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}
```
```rust
pub mod hosting {
    pub fn add_to_waitlist() {}
}
```