Rustを触ってみた【導入編】

# はじめに
前々から気になっていたRustを折角の休みだし触ってみることにしました！
タイトル通りインストールからいけるとこまでやってみました！
学習の参考やスケジュールの目処になれば幸いです。
ちなみに筆者はまともにこれ書けるぜ！ってレベルの言語は一個もないですw
Lambdaでなんちゃってクソコード書くのが精一杯のレベルなので。。

# Rustとは？
公式ドキュメント : https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/
日本語対応しているので嬉しいですね！ざっと知っていた知識としては以下です。

 - 比較的新しめの言語
 - C/C++と比べて安全な設計をした言語
 - C/C++と同等の処理速度を発揮
 - C/C++の代替えを目的として発足
 - 静的型付けのコンパイラ言語
 - Mozillaが推している言語

色々調べてわかったこと

 - 標準でパッケージマネージャー/テスト機能が付いている
 - 型の種類がめちゃくちゃ豊富
 - 関数内部での型推論がイケてる！
 - 静的に変数の寿命がわかる
 - 自動でメモリを解放してくれる
 - デフォルトでスレッドセーフが担保されている変数
 - ムーブセマンティクスを言語レベルで利用可能
 - StackOverflowの**「最も愛されているプログラミング言語」で1位を4年連続獲得**している！(2016年/2017年/2018年/2019年)

C/C++を引き継いでいるので個人的にはマクロをこねこねしていた時代を思い出して、懐かしい気持ちになりながら楽しく学べました！(嫌いな方はすごく嫌いかもしれないですw)

```rust:こんなのとか
fn addition<'a>(a:i32,b:i32)->&'a i32{
    let c=a+b;
    return &c;
}
```
では早速やってきます！

# インストール
インストールはすごく簡単です！
以下公式ページのトップからコマンドラインにコピペで終わりですw
https://www.rust-lang.org/tools/install

```bash:Install
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
info: downloading installer

Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

It will add the cargo, rustc, rustup and other commands to
Cargo's bin directory, located at:

  /Users/user/.cargo/bin

This can be modified with the CARGO_HOME environment variable.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /Users/user/.rustup

This can be modified with the RUSTUP_HOME environment variable.

This path will then be added to your PATH environment variable by
modifying the profile files located at:

  /Users/user/.profile
/Users/user/.bash_profile

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


   default host triple: x86_64-apple-darwin
     default toolchain: stable
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1

info: profile set to 'default'
info: default host triple is x86_64-apple-darwin
info: syncing channel updates for 'stable-x86_64-apple-darwin'
info: latest update on 2019-12-19, rust version 1.40.0 (73528e339 2019-12-16)
info: downloading component 'cargo'
  3.7 MiB /   3.7 MiB (100 %)   3.7 MiB/s in  1s ETA:  0s
info: downloading component 'clippy'
info: downloading component 'rust-docs'
 11.9 MiB /  11.9 MiB (100 %)   3.5 MiB/s in  3s ETA:  0s
info: downloading component 'rust-std'
 16.2 MiB /  16.2 MiB (100 %)   3.7 MiB/s in  4s ETA:  0s
info: downloading component 'rustc'
 54.9 MiB /  54.9 MiB (100 %)   3.5 MiB/s in 15s ETA:  0s
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 11.9 MiB /  11.9 MiB (100 %)   2.6 MiB/s in  4s ETA:  0s
info: installing component 'rust-std'
 16.2 MiB /  16.2 MiB (100 %)  11.2 MiB/s in  1s ETA:  0s
info: installing component 'rustc'
 54.9 MiB /  54.9 MiB (100 %)  14.6 MiB/s in  3s ETA:  0s
info: installing component 'rustfmt'
info: default toolchain set to 'stable'

  stable installed - rustc 1.40.0 (73528e339 2019-12-16)


Rust is installed now. Great!

To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done
automatically.

To configure your current shell run source $HOME/.cargo/env
```

パスも追加してくれているみたいなので`source ~/.bash_profile`ですぐにバージョン確認ができます。

```bash:versions
$ source ~/.bash_profile
$ 
$ rustc --version
rustc 1.40.0 (73528e339 2019-12-16)
$ 
$ cargo --version
cargo 1.40.0 (bc8e4c8be 2019-11-22)
$ 
$ rustdoc --version
rustdoc 1.40.0 (73528e339 2019-12-16)
```

ではHelloworldまで一気にやっちゃいましょう。

```bash:hello_world
$ mkdir hello_world;cd hello_world
$ 
$ touch main.rs
$ 
$ ll
total 0
drwxr-xr-x  3 user  staff   96 12 30 11:08 .
drwxr-xr-x  4 user  staff  128 12 30 11:08 ..
-rw-r--r--  1 user  staff    0 12 30 11:08 main.rs
$ 
```

```rust:main.rs
fn main() {
    println!("Hello, world!");
}
```

```bash:build
$ rustc main.rs
$ 
$ ls -l
total 552
drwxr-xr-x  4 user  staff     128 12 30 11:09 .
drwxr-xr-x  4 user  staff     128 12 30 11:08 ..
-rwxr-xr-x  1 user  staff  276832 12 30 11:09 main
-rw-r--r--  1 user  staff      45 12 30 11:09 main.rs
$ ./main
Hello, world!
```

簡単ですね！ちなみに下記のような方法でも可能です。

```bash:cargo&nbsp;new
$ mkdir cargo_new;cd cargo_new
$ cargo new helloworld
     Created binary (application) `helloworld` package
$ 
$ ls -l
total 0
drwxr-xr-x  3 user  staff   96 12 30 11:12 .
drwxr-xr-x  6 user  staff  192 12 30 11:12 ..
drwxr-xr-x  4 user  staff  128 12 30 11:12 helloworld
$ 
$ cd helloworld
$ 
$ ls -l
total 8
drwxr-xr-x  4 user  staff  128 12 30 11:12 .
drwxr-xr-x  3 user  staff   96 12 30 11:12 ..
-rw-r--r--  1 user  staff  233 12 30 11:12 Cargo.toml
drwxr-xr-x  3 user  staff   96 12 30 11:12 src
$ 
$ ll src
total 8
drwxr-xr-x  3 user  staff   96 12 30 11:12 .
drwxr-xr-x  6 user  staff  192 12 30 11:13 ..
-rw-r--r--  1 user  staff   45 12 30 11:12 main.rs
```

```rust:src/main.rs
fn main() {
    println!("Hello, world!");
}
```

```bash:cargo&nbsp;run
$ cargo run
   Compiling helloworld v0.1.0 (/Users/user/cargo_new/helloworld)
    Finished dev [unoptimized + debuginfo] target(s) in 3.21s
     Running `target/debug/helloworld`
Hello, world!  #Hello, world!が表示される
$ 
$ ls -l
total 16
drwxr-xr-x  6 user  staff  192 12 30 11:13 .
drwxr-xr-x  3 user  staff   96 12 30 11:12 ..
-rw-r--r--  1 user  staff  142 12 30 11:13 Cargo.lock  #.lockファイルが生成される
-rw-r--r--  1 user  staff  233 12 30 11:12 Cargo.toml
drwxr-xr-x  3 user  staff   96 12 30 11:12 src
drwxr-xr-x  4 user  staff  128 12 30 11:13 target
```

```conf:Cargo.lock
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "helloworld"
version = "0.1.0"
```

[Cargo.tomlリファレンス](https://doc.rust-lang.org/cargo/reference/manifest.html)

```bash:tree
$ tree -d
.
├── src
└── target
    └── debug
        ├── build
        ├── deps
        │   └── helloworld-f52023378caf7043.dSYM
        │       └── Contents
        │           └── Resources
        │               └── DWARF
        ├── examples
        ├── helloworld.dSYM -> deps/helloworld-f52023378caf7043.dSYM
        └── incremental
            └── helloworld-iqi0rwk4kl00
                └── s-fj8ked5lur-u8cgl5-1x8ryuh7rlm9x
```

Hello worldくらいならファイル作成してしまった方が楽ですが、テンプレートが生成できるということは何か役に立つのでしょう！楽しみにして進めていきます。

### main関数
>main関数は特別で、全てのRustプログラムの開始点になります。 

と記載があるとおりmain関数はどこにあろうとまずは実行されることに留意しなければいけません。
上からドバーっと実行されるわけではなくmainが開始点になるということを忘れてしまうと思わぬ動作を産んでしまうので注意しましょう。(その前にコンパイルで怒られることがほとんだと思いますが…)

```rust
fn main() {
    hello("hello, world from function");
}

fn hello(message: &str) {
    println!("{}",message);
}
```

# 数当てゲーム
公式リファレンスに倣って数当てゲームを作ってみます。
まずは`cargo new`を利用して必要なファイルを作成していきます。

```bash
$ 
uluru514:into-rust user$ cargo new guessing_game --bin
     Created binary (application) `guessing_game` package
$ 
$ cd guessing_game
$ 
$ ll
total 16
drwxr-xr-x  6 user  staff  192 12 30 13:03 .
drwxr-xr-x  8 user  staff  256 12 30 13:03 ..
-rw-r--r--  1 user  staff  236 12 30 13:03 Cargo.toml
drwxr-xr-x  3 user  staff   96 12 30 13:03 src
```
できた`src/main.rs`を下記に書き換えます。

```rust:src/main.rs
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`して動くことを確認してみます。

```
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
1
You guessed: 1
```
ちゃんと動きました。
中身を見ていきましょう。

### use(ライブラリ追加)

```rust:ライブラリインポート
use std::io;
// JSやPythonで言うところの import
```

Rustの標準で読み込まれるデフォルトのライブラリを[プレリュード](https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/std/prelude/index.html)と言いますが、あまり多くのライブラリが含まれていないため大抵は`use`を使ってインポートが必要です。

### mut(変数の可変化)
https://doc.rust-jp.rs/the-rust-programming-language-ja/1.9/book/mutability.html

```rust:murability
    let mut guess = String::new();
```

通常JavaScriptなど`let`を使う場合、変数として扱われるためデフォルトで後から値を変更することが可能ですが、Rustの場合`let`を宣言していてもデフォルトではイミュータブル(不変)な変数として扱われるため下記のようなコードはエラーとして扱われます。

```rust:no&nbsp;declaire&nbsp;mut
fn main() {
    let message = "immutable strings";
    message = "change value";
    
    println!("{}", message)
}
```
結果はこうなります。

```rust:error
$ cargo run
   Compiling hello_world v0.1.0 (/Users/user/demo-rust/hello_world)
error[E0384]: cannot assign twice to immutable variable `message`
 --> src/main.rs:3:5
  |
2 |     let message = "immutable strings";
  |         -------
  |         |
  |         first assignment to `message`
  |         help: make this binding mutable: `mut message` 　　　　　　　　　　 //ミュータブルな変数にするように言われる
3 |     message = "change value";
  |     ^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable  //イミュータブルな変数だと怒られる

error: aborting due to previous error

For more information about this error, try `rustc --explain E0384`.
error: could not compile `hello_world`.

To learn more, run the command again with --verbose.
```
これを`let message`から`let mut message`に変更してあげることで通るようになります。

```rust:mutable&nbsp;variable
fn main() {
    let mut message = "immutable strings";
    message = "change value";
    
    println!("{}", message)
}
```

```rust:result
$ cargo run
   Compiling hello_world v0.1.0 (/Users/user/demo-rust/hello_world)

    Finished dev [unoptimized + debuginfo] target(s) in 0.85s
     Running `target/debug/hello_world`
change value
```
このように変数を扱う際は、それが不変であるか否かの判断が必要です。

### メソッドの利用
今度はこちらのコードの処理を追っていきましょう。

```rust
    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");
```
上記コードの中でメソッドを呼び出しています。

`io::stdin()`については`use std::io;`の関数なので`std::io::stdin`として呼び出すことも可能です。

```rust
    std::io::stdin().read_line(&mut guess)
        .expect("Failed to read line");
```
また`.read_line`は`std::io::stdin`に含まれるメソッドです。
`.read_line(&mut guess)`となっており、`let mut guess = String::new();`からの文字列の入力を待ち受けています。
メソッドに関してはインスタンス内でのみ利用が可能となっています。
`.expect();`はエラーハンドリングに関する[std::result::Result](https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/std/result/enum.Result.html)のメソッドで[panic!](https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/std/macro.panic!.html)の発生を防止しています。

このあたりは**mut**は少し特殊ですが、Rust独特というよりも静的言語っぽいなっていう感じです。

## 秘密の数を生成する
Rustの標準ライブラリには乱数がないので、[randクレート](https://crates.io/crates/rand)を利用して乱数を生成できるよう追加します。

### Cargo.toml
標準の場合

```conf:Cargo.toml
[package]
name = "guessing_game"
version = "0.1.0"
authors = ["hoge-fuga <hogehoge@fuga.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
```
こちらに下記コマンドを実施して依存関係を追加してあげます。

```bash
dpd='[dependencies]

rand="0.3.0"'
echo "$dpd" >> Cargo.toml
```

```conf:add&nbsp;dependencies
[package]
name = "guessing_game"
version = "0.1.0"
authors = ["hoge-fuga <hogehoge@fuga.com>"]
edition = "2018"

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

[dependencies]

rand="0.3.0"
```
ちなみに`[dependencies]`のバージョン表記は様々あります。

|表記|意味|
|---|---|
|hoge=1.2.0 or rand=^1.2.0|v1.2.0と互換性のあるものを使う|
|hoge="=1.2.0"|v1.2.0を指定して使う|
|hoge=~1.2.0|1.2.0 <1.3.0のバージョンを使う|
|hoge=1.2.＊|上記と同じ ※互換性を失う可能性があるため非推奨|
|hoge>= 1.2.0, < 1.3.0|1.2.0~1.3.0の間を使う|

ではパッケージをインストールするため`cargo build`を実施します。

```bash:cargo&nbsp;build
$ cargo build
    Updating crates.io index
  Downloaded rand v0.3.23
  Downloaded rand v0.4.6
  Downloaded libc v0.2.66
   Compiling libc v0.2.66
   Compiling rand v0.4.6
   Compiling rand v0.3.23
   Compiling guessing_game v0.1.0 (/Users/user/demo-rust/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 1m 10s
```
完了するとCargo.lockファイルも更新がかかります。

<details><summary>Cargo.lock</summary><div>

```conf
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "guessing_game"
version = "0.1.0"
dependencies = [
 "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "libc"
version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "rand"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
 "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[metadata]
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
```

</div></details>

乱数に必要な`rand`のインストールも完了したので利用するようにコードを書き換えます。

```rust:src/main.rs
extern crate rand;

use std::io;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_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);
}
```
実行結果としては以下になります。

```rust:result
$ cargo run
   Compiling guessing_game v0.1.0 (/Users/user/demo-rust/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.58s
     Running `target/debug/guessing_game`
Guess the number!
The secret number is: 24
Please input your guess.
3
You guessed: 3
```

こちらも分解して見ていきましょう。

### トレイト
[トレイト](https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/traits.html)とは？
>トレイトはある型が提供しなければならない機能をRustのコンパイラに伝える言語機能です。

わかるような、わからないような…tsで言うところの`*.d.ts`的な？
もう少しドキュメントを読み込んでみます。

`trait`はメソッドを集めたものであり、`trait`を型に実装することによって、その型の値がメソッドを提供することができるようになります。
実際に下記例をとって見ると`trait HasArea {}`は関数`area`がプリミティブ型`f64`で戻ってくること以外は記載がありません。
その下にメソッドとして`impl トレイト for アイテム`が定義されており、
スタック上の値(`self`)として`radius`を受け取り乗算し、その結果をさらにπ(`std::f64::consts::PI`)で乗算する円の面積を求める計算式になっていることがわかります。

```rust
struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

trait HasArea {
    fn area(&self) -> f64;
}

impl HasArea for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}
```

上記でトレイトは定義できましたが、実際に利用する際には**境界**という考え方が重要になってきます。
>境界(Bounds)とはある1つの型または トレイト における制約のことです。例えば、ある関数がとる引数に境界が設定されたとすると、その関数に渡される型は設定された制約に必ず従わなければなりません。

[公式ドキュメント引用](https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/glossary.html#%E5%A2%83%E7%95%8C)

ざっくりといってしまうと、型がどのトレイトを使うのか？を明示的にしてあげる必要があります。
以下2例でトレイト境界を宣言していますが、上はエラーになり下は`HasArea`を利用するよう明示しているため利用が可能になります。

```rust:fail&nbsp;&&nbsp;success
// Error pattern
fn print_area<T>(shape: T) { // T -> トレイトを指定していないためareaメソッドが実装されていない扱いになる
    println!("This shape has an area of {}", shape.area());
}

// Success pattern
fn print_area<T: HasArea>(shape: T) {
    println!("This shape has an area of {}", shape.area());
}
```
これを踏まえて実際のコードに反映すると、

```rust:add&nbsp;trait
trait HasArea {
    fn area(&self) -> f64;
}

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl HasArea for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

fn print_area<T: HasArea>(shape: T) {
    println!("This shape has an area of {}", shape.area());
}

fn main() {
    let c = Circle {
        x: 0.0f64,
        y: 0.0f64,
        radius: 1.0f64,
    };

    print_area(c);
}
```

```rust:result
$ cargo run
   Compiling hello_world v0.1.0 (/Users/user/demo-rust/hello_world)

    Finished dev [unoptimized + debuginfo] target(s) in 0.33s
     Running `target/debug/hello_world`
This shape has an area of 3.141592653589793
```
となり、`area`メソッドで定義されている`π * ( 1.0 * 1.0 )`が実行されている。
長くなりましたが、`use rang::Rng;`を冒頭で追加しているのは`.gen_range`メソッドを利用するのに`Rng`トレイトを実装してあげる必要があるからです。

```rust
    fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T
    where
        B1: SampleBorrow<T> + Sized,
        B2: SampleBorrow<T> + Sized,
    {
        T::Sampler::sample_single(low, high, self)
    }
```

https://github.com/rust-random/rand/blob/5643fd5c4f93158350724770c1262ae8fdc8be55/src/lib.rs#L211

## 予想値と比較する
ここまででユーザー入力と乱数生成が可能になりました。
それらを比較するような機能を実装していきます。
全体のコードはこちらです。

```rust:src/main.rs
extern crate rand;

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);

    println!("The secret number is: {}", secret_number);

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    let guess: u32 = guess.trim().parse()
        .expect("Please type a number!");

    println!("You guessed: {}", guess);

    match guess.cmp(&secret_number) {
        Ordering::Less    => println!("Too small!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal   => println!("You win!"),
    }
}
```
`use std::cmp::Ordering;`のライブラリを利用して比較を実施しています。
実行結果は下記です。

```rust:result
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/guessing_game`
Guess the number!
The secret number is: 60
Please input your guess.
3
You guessed: 3
Too small!
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/guessing_game`
Guess the number!
The secret number is: 2
Please input your guess.
2
You guessed: 2
You win!
```
このように比較が行われるようになりました。
こちらも分解して見ていきましょう。

### parse
比較するにあたって文字コードを揃えてあげる必要があります。
今までのコードだと`guess = String::new();`なので型推論から文字列と判断されてしまうため`secret_number`との比較ができません。
なので下記2行を用いて、`guess`を数値へと変換してあげる必要があります。

```rust:parse
    let guess: u32 = guess.trim().parse()
        .expect("Please type a number!");
```

`let guess: u32`によって`guess`のタイプが[u32](https://doc.rust-lang.org/std/primitive.u32.html)であることが明示的にわかります。
`.parse()`メソッドによって文字列が数値へと変換されるのですが、上記で`u32`に指定されているため**符号なし32bit整数**に変換されます。
これで後続の`secret_number`との比較が可能になります。

### シャドーイング
上記の場合`let mut guess = String::new();`で定義しており、`guess`はミュータブルな変数として扱わるため再度`let guess: u32 = guess.trim().parse()`で定義し直す(以前定義したものを隠す)事ができます。これにより、別の変数を用いて変換することができます。

### ループ
`loop{}`を利用することで処理を繰り返す事ができます。
これを利用してsecret_numberと入力値が一致するまでのロジックを実装していきます。

```rust:src/main.rs
extern crate rand;

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);

    println!("The secret number is: {}", secret_number);

    loop {  // 当たるまで繰り替えす処理内容
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

        let guess: u32 = guess.trim().parse()
            .expect("Please type a number!");

        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;  // 勝った場合の戻り値をトリガーとしてloop処理を終了させる
            }
        }
    }
}
```
`break;`を利用して繰り返し処理を抜けるのはCやC++は当然ですが、bashなんかでも利用するので馴染みがあると思います。
また以下の一文を追加して文字列を入力した際に以上終了せず、繰り返し処理を実行するようにしていきます。

```rust:expect&nbsp;strings
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };
```
一通りのロジックは完成しましたが、これは数字当てゲームなので`secret_number`が見えていては意味がありませんのでこちらを表示しないよう不要な処理を消してしまいましょう。

```rust:src/main.rs
extern crate rand;

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);

    // println!("The secret number is: {}", secret_number);  // secret_numberを表示してしまう不要な処理

    loop {
        println!("Please input your guess.");

        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;
            }
        }
    }
}
```
実行結果は下記の通りです。

```rust:result
$ cargo run
   Compiling guessing_game v0.1.0 (/Users/user/demo-rust/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 0.54s
     Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
2
You guessed: 2
Too small!
Please input your guess.
90
You guessed: 90
Too big!
Please input your guess.
test
Please input your guess.
43
You guessed: 43
You win!
```
これで数字当てゲームは一通り終わりです。
まだまだチュートリアルはありますが、今回は一旦ここまでにしておきます。

# 所感
個人的にはすごく楽しかったです！
静的言語の方が好きなのもありますが、なんとなく馴染みやすかったです。
あとは`cargo`が便利なのもあり、buildが非常に楽でよかったです！(CとかC++でmakefile頑張ってたのが嘘みたい。。)
ただだらーっとコード書いていくだけであれば、5分とかで終わると思いますが**[所有権](https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/ownership.html)**や**トレイト**などの概念を理解するのにドキュメントを飛び飛びで追っていったので3時間くらいかかりました。。
しかし導入はすごく簡単ですし他の言語に慣れている方なら割とスッと入れると思いますので、是非みなさんも一度触れてみてはいかがでしょうか？