Rustの練習帳で練習してみた

# はじめに
ちょっと前から気になっていたプログラミング言語「Rust」を覚えようと思い、
とにかく手を動かそうと思って、oreillyの「Rustの練習帳」に手を付けてみた。

https://www.oreilly.co.jp/books/9784814400584/

この本は、読めばRustの知識がつく・読むとRustが書ける、というようなものではなく、
お題、ひな形や最低限の条件が書いてあって、それに沿って自分でRustを書いて覚えるという本である。

そのため、本に書いてあることをただ読んで、書いてあることをそのまま書くだけでは、
Rustのプログラムが完成しないようになっている。
（一応完成例があるので、それを先に読めば完成するが...）

この本でRustを練習していったなかで、自分で見つけたエラー解決方法や
自分が実施したオリジナル要素を、備忘録として、この記事に残すこととした。

# 本記事の目的
### Rustの楽しさを広める
本記事に限らず、自分がRustの記事を書く時の目的は
「Rustの楽しさを広めて、Rustエンジニアを増やす」
である。

### 本記事の目的
で、この記事を読んだ人が
+ Rustの練習帳で躓いたことが解決する
+ Rustで躓いたことを解決し、Rustに対するモヤモヤが減る
+ Rustに触れやすくなる
+ Rustが楽しくなる
ことを目的とする。
（さすがに楽しくはならないかも）

### 本記事の内容
Rustの練習帳での練習において、解決に苦労したエラーだったり、練習帳にはないオリジナルなことを記載する。
これらの内容を見ることで、スムーズにRust練習ができることを目指す。

**なおこの記事は、Rustの練習帳を進めながら執筆しているため、
内容は予告なしに追加・変更することがあることをご注意ください。**

# つまづいたこと
練習帳通りに進めていたら、エラーや予想通りに動かない事態が多々ある。
その中で、特に解決が困難だったことを記録する。

### main.rs から 自クレート内のモジュールを読み込みできない
```rust:main.rs
fn main() {
    if let Err(e) = project1::get_args().and_then(project1::run()) {
        eprintln!("{}", e);
        std::process::exit(1);
    }
}
```

この本では、main.rsはプログラムを実行する際のエントリポイントであり、
基本的にはこの作りにするといったような事が書いてあった。

で、実際の動作である、get_args()とrun()は、
src/lib.csというファイルに書くと書いてあった。

```rust:lib.rs
pub fn run(struct: Struct) -> Result<()> {
    println!("{:#?}", struct);
    Ok(())
}

pub fn get_args() -> Result<Struct> {
    let matches: ArgMatches = App::new("command")
        .version("0.1.0")
        .author("Ken")
        .about("Rust command")
        .arg(
            Arg::with_name("files")
            .value_name("FILE")
            ...// 省略
        )
        .arg(
            ...// 省略
        )
        .get_matches();

    Ok(Struct {
        // 省略
    })
}
```

こんな感じで、**libs.rs**というファイルを作って、
中に実際の処理を実装した。

で、`cargo run` をしたところエラー。
```
use of undeclared crate or module project1
```

srcフォルダの中にファイルを作って、その中に実装したはずのなのに...
と原因を調べていたら、実装ファイル名がlib**s**.rs だったのが問題。
どうやらuseなしで自クレートのモジュールを使用する場合は、
必ず**lib.rs**というファイル名にするらしい。

(参考：[ ファイル分割によるクレート分割、モジュール分割、パッケージ分割](https://qiita.com/kerupani129/items/bd41d8a07daa31256aab))

# オリジナルなこと
### AWSで "いつでもどこでもRustの練習"
自分のようなスタバ好きは、家でも外でもRustの練習をしたくなる。
しかしRustの練習帳は、ローカルPCでの練習を想定している。
そのため常に同じPCを使用しないと、作業途中のコードなどが引き継げない。

ということで、以下の2つを試してみた。
1. OneDriveなどにRustコードを入れる
1. AWS にRust用インスタンスを作る

1.でやってみたところ、buildするたびに大量のファイル更新と
更新メッセージボックスが頻繁に出てきて、目障りとなってしまった。

2.であれば、最初からLinux環境を作ってそのまま動かすことができるので、
いつでもどこでもやりやすいと思い、AWSのEC2にRust環境を構築した。
（Rustの練習帳はLinuxでの動作が紹介されている。）

どのような環境を作ったかは、時間があれば記載する予定。
+ 無料枠で使える最低限のEC2インスタンスを作る
+ その中にRust環境を作る
+ VSCodeでSSHを出来るようにする
+ VSCodeでRust用EC2にSSH接続して使用する

### clap V4 の利用
練習帳では、CLIを作成するために、Rustのclapクレートを使用している。
ただし、紹介されているclapのクレートが2.33と古いバージョンである。

練習していくなかで、なかなかとっかかりづらいところがあった。
それはclapで使用されている名前類がわかりづらいこと。
clapでのコマンドライン作成は何度もするのだが、
いつも何を書けばいいかわからなくて、前のコードを見て、関数などをコピーしている。

自分がわかりづらいと感じたclapの名前類↓
```rust
// clapを使用する際のuse
// Appはコマンドラインを作るためのクレート
// ArgはAppで使用する引数
use clap::{App, Arg} // AppってCLI以外も指すのかな？

// コマンドラインを新規作成する関数
let matches: ArgMatches = App::with_name("command") // command という名前...with?
```

他にもいくつかあるが、clapの名前が直感と異なるので、
これをしたいとき、何と入力すればよいかがすぐ出てこなかった。

で、何を使えばいいか調べるため、clapのドキュメントを読んだところ、
1. 今はバージョンが2.33ではなく、4.5になっている。
1. 破壊的変更が多いのか、使用できないクレートや関数が多々ある。

ことにカルチャーショックを覚えた。
V4のドキュメントを見ると、今は幾分わかりやすくなっていた。

そんなことで、練習帳には載っていない、V4でclapを使用する際の
主な変更点を残すことにした。

**主な2.33→4.5の変更点**
| 2.33 | 4.5 | 備考 |
|:----:|:---:|:----:|
| clap::App | clap::Command | Commandの方がCLIっぽい |
| Arg::with_name  | Arg::new  | newの方が作る感じがする |
|  ArgMatch::values_of_lossy | ArgMatch::get_many  | get_manyの方が文字数少ない |
| take_values(false) | num_args(0) | 引数ないのを引数ゼロと表す |
| multiple | num_args(1..) | 引数1個**以上**と表す |

練習していく中で、見つけたものを随時追加予定。

4.5の方が、直感的でわかりやすい名前になっていたり、
面白い表現になっている。

もっと知りたい方は、clapの公式ドキュメントを参照。
↓↓↓↓↓

https://docs.rs/clap/latest/clap/

# (随時追加予定）