[Rust] チュートリアル⑤　並列性〜パターン記法まで

# はじめに
Rustのチュートリアルのメモです④。

# リンク集

[C++入門](https://amzn.to/2Nf1ntW)
[プログラミングRust (日本語) ](https://amzn.to/2Bs7vvS)
[プログラミング言語Rust入門](https://amzn.to/2BkGP0n)
[実践Rust入門](https://amzn.to/2zRbu4W)

[std::検索](https://doc.rust-lang.org/stable/std/)


# 並行性

平行性を安全かつ効率的に扱うことは、Rustの別の主な目標

並行プログラミング: プログラムの異なる部分が独立して実行

並列プログラミング: プログラムの異なる部分が同時に実行

多くのコンピュータが複数のプロセッサの利点を活かすようになるにつれ、重要度を増している

歴史的に、これらの文脈で行うプログラミングは困難で、エラーが起きやすいものだった
Rustはこれを変える！

所有権と型システムは、メモリ安全性と並行性問題を管理するのに役立つ一連の強力な道具
所有権と型チェックを活用することで、多くの並行性エラーは、実行時エラーではなくコンパイル時エラーになる
故に、実行時に並行性のバグが起きた状況と全く同じ状況を再現しようと時間を浪費させるよりも、不正なコードはコンパイルを拒み、問題を説明するエラーを提示する

高級言語は一部の制御を失う代わりに抽象化することから恩恵を受ける
ところが、低級言語は、どんな場面でも最高のパフォーマンスで解決策を提供すると想定され、ハードウェアに関してはほとんど抽象化はしない
そのため、Rustは、自分の状況と必要性に適した方法がなんであれ、問題をモデル化するための色々な道具を備えている


## スレッドを使用してコードを同時に走らせる

多くの現代のOSでは、実行中のプログラムのコードはプロセスで走り、OSは同時に複数のプロセスを管理する
自分のプログラム内で、独立した部分を同時に実行できる
これらの独立した部分を走らせる機能をスレッドと呼ぶ

プログラム内の計算を複数のスレッドに分けると、パフォーマンスが改善する
プログラムが同時に複数の作業をするため複雑度も増す
スレッドは同時に走らせることができるので、異なるスレッドのコードが走る順番に関して、本格的に保証はない


- スレッドがデータやリソースに矛盾した順番でアクセスする競合状態　
- ２つのスレッドがお互いにもう一方がもっているを待ち、両者が継続するのを防ぐデッドロック
- 特定の状況でのみ起き、確実な再現や修正が困難なバグ

多くのOSで、新規スレッドを生成するAPIが提供されており、生成するモデルを時に1:1と呼び、１つのOSスレッドに対して１つの言語スレッドを意味する

プログラミング言語が提供するスレッドは、グリーンスレッドとして知られ、このグリーンスレッドを使用する言語は、それを異なる数のOSスレッドの文脈で実行する
このため、グリーンスレッドのモデルはM:Nモデルとよばれる
M個のグリーンスレッドに対して、N個のOSスレッドがあり、MとNは必ずしも同じ数字ではない


### spawnで新規スレッドを生成する

use std::thread;
use std::time::Duration;

fn main() {
	// 新規スレッドを立ち上げる

	// この関数では、新しいスレッドは、実行が終わったかどうかにかかわらず、メインスレッドが終了したら停止する

	// ※ numberはスレッドの番号ではない!
	thread::spawn(|| {
		for i in 1..10 {
			println!("hi number {} from the spawned thread!", i);
			thread::sleep(Duration::from_millis(1));
		}
	});

	for i in 1..5 {
		println!("hi number {} from the main thread!", i);
		thread::sleep(Duration::from_millis(1));
	}
}


// output
hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
```


### joinハンドルで全スレッドの終了を待つ

先のコードは、メインスレッドが終了するためにほとんどの場合、立ち上げたスレッドがすべて実行されないだけでなく、立ち上げたスレッドが実行されているかどうかも保証できない

原因は、スレッドの実行順に保証がないから

thread::spawnの戻り値を変数に保存することで、立ち上げたスレッドが実行されなかったり、完全には実行されなかったりする問題を修正することができる

thread::spawnの戻り地の型はJoinHandle
JoinHandleは、そのjoinメソッドを呼び出した時にスレッドの終了を待つ所有された値


```rust:thread::spawnのJoinHandleを保存してスレッドが完了するのを保証する

use std::thread;
use std::time::Duration;

fn main() {
	let handle = thread::spawn(|| {
		for i in 1..10 {
			println!("hi number {} from the spawned thread!", i);
			thread::sleep(Duration::from_millis(1));
		}
	});

	for i in 1..5 {
		println!("hi number {} from the main thread!", i);
		thread::sleep(Duration::from_millis(1));
	}

	// handle.join()呼び出しのためにメインスレッドは待機し、立ち上げたスレッドが終了するまで終わらない
	handle.join().unwrap();
}

// output
hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!
```

ハンドルに対してjoinを呼び出すと、ハンドルが表すスレッドが終了するまで現在実行中のスレッドをブロックする
スレッドをブロックするとは、そのスレッドが動いたり、終了したりすることを防ぐこと


```rust:handle.join()メソッドをforループの前に移動した場合

use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

	// スレッドの立ち上げと終了が終わった後にForが実行される
    handle.join().unwrap();

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}

//output
hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
hi number 3 from the spawned thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!
hi number 1 from the main thread!
hi number 2 from the main thread!
hi number 3 from the main thread!
hi number 4 from the main thread!
```


### スレッドでmoveクロージャを使用する

thread::spawnは立ち上げたスレッドでメインスレッドのデータを使用するには必要な値をキャプチャしなければならない


```rust:立ち上げたスレッドの起動時間が分からないので、vへの参照が常に有効か把握できずコンパイル失敗する

use std::thread;

fn main() {
	let v = vec![1, 2, 3];

	let handle = thread::spawn(|| {
		// こちらがベクタ: {:?}
		println!("Here's a vector: {:?}", v);
	});

	handle.join().unwrap();
}
```

```rust:クロージャに所有権を強制的に奪わせる

use std::thread;

fn main() {
	let v = vec![1, 2, 3];

	let handle = thread::spawn(move || {
		// こちらがベクタ: {:?}
		println!("Here's a vector: {:?}", v);
	});

	handle.join().unwrap();
}

// output
Here's a vector: [1, 2, 3]
```


##　メッセージ受け渡しを使ってスレッド間でデータを転送する

人気度を増してきている安全な並行性を保証する１つのアプローチがメッセージ受け渡しで、スレッドやアクターがデータを含むメッセージを相互に送り合うことでやり取りする

「メモリを共有することでやりとりするな；代わりにやり取りすることでメモリを共有しろ」 by Go言語のスローガン

```rust
use std::sync::mpsc;
use std::thread;

fn main() {
	let (tx, rx) = mpsc::channel();

	// txを新規スレッドにムーブ
	thread::spawn(move || {
		let val = String::from("hi");
		tx.send(val).unwrap();
	});

	// メインスレッドで受取出力する
	let received = rx.recv().unwrap();
	// 値は{}です
	println!("Got: {}", received);
}
```


### チャンネルと所有権の転送

安全な並行コードを書く手助けをしてくれるので、所有権規則は、メッセージ送信で重要な役割を担っている
並行プログラミングでエラーを回避することはRustプログラム全体で所有権について考える利点


```rust:チャンネルに送信後にvalの使用を試みる

	let (tx, rx) = mpsc::channel();

	// txを新規スレッドにムーブ
	thread::spawn(move || {
		let val = String::from("hi");
		tx.send(val).unwrap();
		println!("val is {}", val); // valの値は新規スレッドにムーブされているのでエラー
	});


//output
error[E0382]: borrow of moved value: `val`
  --> src/main.rs:11:25
   |
9  |         let val = String::from("hi");
   |             --- move occurs because `val` has type `std::string::String`, which does not implement the `Copy` trait
10 |         tx.send(val).unwrap();
   |                 --- value moved here
11 |         println!("val is {}", val);
   |                               ^^^ value borrowed here after move

````

send関数は引数の所有権を奪い、値がムーブされると、受信側が所有権を得る
これにより、送信後に誤って再度値を使用するのを防ぐ
所有権システムが、万事問題ないことを確認できる


### 複数の値を送信し、受信側が待機するのを確かめる　

```rust

fn main() {
	let (tx, rx) = mpsc::channel();

	// txを新規スレッドにムーブ
	thread::spawn(move || {
		let vals = vec![
			String::from("hi"),
			String::from("from"),
			String::from("the"),
			String::from("thread"),
		];
		// vecある要素を個別に送信し1秒sleep
		for val in vals {
			tx.send(val).unwrap();
			thread::sleep(Duration::from_millis(1));
		}
	});

	// メインスレッドで受取出力する
	for received in rx {
		println!("Got: {}", received);
	}
}

// output
Got: hi
Got: from
Got: the
Got: thread
```


### 転送機をクローンして複数の生成器を作成する

最初のスレッドを立ち上げる前に、チャンネルの送信側に対してcloneを呼び出す
これにより、最初に立ち上げたスレッドに渡せる新しい送信ハンドルが得られる
元のチャンネルの送信側は、２番目に立ち上げたスレッドに渡す
これにより２つのスレッドが得られ、

```rust
fn main() {
	let (tx, rx) = mpsc::channel();

	// txの生成器の複製
	let tx1 = mpsc::Sender::clone(&tx);

	// tx1
	thread::spawn(move || {
		let vals = vec![
			String::from("hi"),
			String::from("from"),
			String::from("the"),
			String::from("thread"),
		];
		// vecある要素を個別に送信し1秒sleep
		for val in vals {
			tx1.send(val).unwrap();
			thread::sleep(Duration::from_millis(1));
		}
	});

	// tx1
	thread::spawn(move || {
		let vals = vec![
			String::from("more"),
			String::from("messages"),
			String::from("for"),
			String::from("you"),
		];
		// vecある要素を個別に送信し1秒sleep
		for val in vals {
			tx.send(val).unwrap();
			thread::sleep(Duration::from_millis(1));
		}
	});
	// メインスレッドで受取出力する
	for received in rx {
		println!("Got: {}", received);
	}
}
```


## 状態共有並行性

メモリ共有並行性とは、スマートポインタの複数の所有権に似ている
複数のスレッドが同時に同じメモリ位置にアクセスできる


### ミューテックスを使用して一度に１つのスレッドからデータにアクセスすることを許可する

ミューテックスとは、どんなときも１つのスレッドにしかなんらかのデータへのアクセスを許可しない

mutual exclusion(相互排他)の略

2つの規則

- データを使用する前にロックを獲得する
- ミューテックスが死守しているデータの使用が終わったら、他のスレッドがロックを獲得できるように、データをアンロックしなければならない

ミューテックスの管理は、正しく行うのに著しく技巧を要することがあるので、多くの人がチャンネルに熱狂的になる
しかしながら、Rustの型システムと所有権規則のおかげで、ロックとアンロックをおかしくすることはない


#### ミューテックスの例

マイクが１つかないパネルディスカッション
話す前に申し出る
話し終わったら、次の人に渡す
マイクを渡さなければ、次の人は話せない

共有されているマイクの管理がうまくいかなければパネルは予定通りに機能しない

```rust

use std::sync::Mutex;

fn main() {
	let m = Mutex::new(5);
	{
		let mut num = m.lock().unwrap();
		*num = 6;

		// mをロックを解除する前に、ロックしようとすると待機状態になりコンパイルが終わらない
		// let mut num2 = m.lock().unwrap();
		// *num2 = 7;
	}
	println!("m = {:?}", m);
}

// output
m = Mutax { data: 6 }


// これならOK
fn main() {
	let m = Mutex::new(5);
	{
		let mut num = m.lock().unwrap();
		*num = 6;
	}
	println!("m = {:?}", m);

	{
		let mut num2 = m.lock().unwrap();
		*num2 = 7;
	}

	println!("m = {:?}", m);
}

// output
m = Mutax { data: 6 }
m = Mutax { data: 7 }
```


### 複数のスレッド間でMutex<T>を共有する


```rust:counterの所有権がムーブしたためエラーになる


use std::sync::Mutex;

fn main() {
	let counter = Mutex::new(0);
	let mut handles = vec![];

	for _ in 0..10 {
		// 最初のループでcounterの所有権がhandleに譲渡
		// 2つめのスレッドでエラーとなり終了
		let handle = std::thread::spawn(move || {
			let mut num = counter.lock().unwrap();
			*num += 1;
		});
		handles.push(handle);
	}

	for handle in handles {
		// 走ってるスレッドを終了する
		handle.join().unwrap();
	}
}

//output
error[E0382]: use of moved value: `counter`
 --> src/main.rs:8:35
  |
4 |     let counter = Mutex::new(0);
  |         ------- move occurs because `counter` has type `std::sync::Mutex<i32>`, which does not implement the `Copy` trait
...
8 |         let handle = std::thread::spawn(move || {
  |                                         ^^^^^^^ value moved into closure here, in previous iteration of loop
9 |             let mut num = counter.lock().unwrap();
  |                           ------- use occurs due to use in closure
```


### 複数のスレッドで複数の所有権

スマートポインタのRc<T>を使用して参照カウンタの値を作って、１つの値に複数の所有権を与えることを応用して、複数のスレッドで複数の所有権を共有してみる

s
```rust
use std::rc::Rc;
use std::sync::Mutex;
use std::thread;

fn main() {
	// 参照カウンタを初期化(スコープに導入)
	let counter = Rc::new(Mutex::new(0));
	let mut handles = vec![];

	for _ in 0..10 {
		let counter = Rc::clone(&counter);
		let handle = thread::spawn(move || {
			let mut num = counter.lock().unwrap();

			*num += 1;
		});
		handles.push(handle);
	}

	for handle in handles {
		handle.join().unwrap();
	}

	println!("Result: {}", *counter.lock().unwrap());
}

// output
error[E0277]: `std::rc::Rc<std::sync::Mutex<i32>>` cannot be sent between threads safely
   --> src/main.rs:12:16
    |
12  |           let handle = thread::spawn(move || {
    |  ______________________^^^^^^^^^^^^^_-
    | |                      |
    | |                      `std::rc::Rc<std::sync::Mutex<i32>>` cannot be sent between threads safely
```

Rc<T>はスレッド間で共有するのは安全でないのでエラーとなる
複数スレッド間で参照カウンタを共有すると間違ったカウントをする恐れがあるため、今後メモリリークや、使用し終わる前に値がドロップされることにつながる可能性のある潜在的なバグにつながる


### Arc<T>で原始的な参照カウント

Arc<T>はRc<T>のような並行な状況で安全に使用できる型
AはAtomicを表し、原始的に参照カウントする型

```rust:Mutex<T>をArc<T>でラップする
use std::sync::{Mutex, Arc};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();

            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Result: {}", *counter.lock().unwrap());
}

// output
Result: 10
```


## SyncとSendトレイトで拡張可能な並行性

これまでの並行性機能のほとんどは標準ライブラリの一部であり言語ではない
並行性を扱う選択肢は、言語や標準ライブラリに制限されない
独自の並行性機能を書いたり、他人が書いたものを利用したりできる

2つの並列性概念 std::markerトレイとのSyncとSend


### Sendでスレッド間の所有権の転送を許可する

SendマーカートレイとはSendを実装した型の所有権をスレッド間で転送できることを示唆する
Rc<T>を含めて一部例外がある
Rc<T>はシングルスレッド環境で使用するために実装されている
Rc<T>の値を不安全にスレッド間で誤って送信することが絶対ないように保証してくれている


### Syncで複数のスレッドからのアクセスを許可する

Syncマーカートレイトは、Syncを実装した型は、複数のスレッドから参照されても安全であることを示唆する
&TがSendなら、型TはSyncであり、参照が他のスレッドに安全に送信できることを意味する
Send同様、基本型はSyncであり、Syncの方からのみ構成される

Sendでなかったのと同じ理由で、スマートポインタのRc<T>もまたSyncではない
Cell<T>系についても同様にSyncではない
Mutex<T>はSyncである


### SendとSyncを手動で実装するのは非安全

SendとSyncトレイとから構成される型は自動的にSendとSyncにもなるので、それらのトレイトを手動で実装する必要はない
マーカートレイとして、実装すべきメソッドさえも何もない
並行性に関連する不変条件を強制することに役立つだけ


# Rustのオブジェクト指向プログラミング機能

オブジェクト指向プログラミングは、オブジェクトで構成される
オブジェクトは、データとそのデータを処理するプロシージャを梱包している
このプロシージャは、典型的にメソッドまたはオペレーションとよばれる


## オブジェクト指向の特徴

Rustはオブジェクト指向
構造体とenumにはデータがあり、implブロックが構造体とenumにメソッドを提供する
オブジェクトとは呼ばれないものの、GoFのオブジェクト定義によると、同じ機能を提供する


### カプセル化は、実装詳細を隠蔽する

オブジェクトの実装詳細は、オブジェクトを使用するコードにはアクセスできないことを意味する
故に、オブジェクトと相互作用する唯一の手段は、その公開APIを通して
オブジェクトを使用するコードは、オブジェクトの内部に到達して、データや振る舞いを直接変更できるべきではない

カプセル化を制御する方法は、pubキーワードを使用して、自分のコードをどのモジュールや型、関数、メソッドを公開するか決められ、規定ではそれ以外のものは全て非公開


## トレイトオブジェクトで異なる型の値を許容する

ベクタの１つの制限を回避するのにenumを定義して異なる型のデータを格納できるようにした
が、時として、ライブラリの使用者が特定の場面で合法になる型のセットを拡張したくなることがある
これをどう実現する可能性があるかを示すために、各アイテムにdrawメソッドを呼び出してスクリーンに描画するという、GUIツールで一般的なテクニックをしてあるリストの要素を走査するGUIツールを作る


### 一般的な振る舞いにトレイトを定義する

guiに欲しい振る舞いを定義するにはdrawという１つのメソッドをもつDrawというトレイトを定義する　
それからトレイトオブジェクトを取るベクタを定義できる
トレイトオブジェクトは、指定したトレイトを実装するある型のインスタンスを指す
&参照やBox<T>スマートポインタなどの、何らかのポインタを指定し、それから関係のあるトレイトを指定することでトレイトオブジェクトを作成する

```rust:VecのBox<Draw>型のトレイトオブジェクト
pub struct Screen {
	// VecのBox<Draw>型のトレイトオブジェクト
	pub components: Vec<Box<Draw>>, 
}
impl Screen {
	// 各コンポーネントに対してdrawメソッドを呼び出すScreenのrunメソッド
	pub fn run(&self) {
		for componet in self.components.iter() {
			componet.draw();
		}
	}
}
```

```rust:ジェネリクスとトレイト教会を使用したScreen構造体とrunメソッドの対立的な実装
pub struct Screen<T: Draw> {
	pub components: Vec<T>, // VecのBox<Draw>型のトレイトオブジェクト
}

impl<T> Screen<T>
where
	T: Draw,
{
	// 各コンポーネントに対してdrawメソッドを呼び出すScreenのrunメソッド
	pub fn run(&self) {
		for componet in self.components.iter() {
			componet.draw();
		}
	}
}
```


## オブジェクト指向デザインパターンを実装する

ステートパターンは、オブジェクト指向デザインパターンの１つ
このパターンの肝は、値が一連のステートオブジェクトで表されるなんらかの内部状態を持ち、その内部の状態に基づいて値の振る舞いが変化する
ステートオブジェクトは、機能を共有する
Rustでは、もちろん、オブジェクトと継承ではなく、構造体とトレイトを使用する
各ステートオブジェクトは、自身の振る舞いと別の状態に変化すべき時を司ることに責任を持つ
ステートオブジェクトを保持する値は、状態ごとの異なるhルマいやいつ状態が移行するかについては何も知らない

ブログ記事のワークフロー

1. ブログ記事は、空の草稿から始まる
2. 草稿ができたら、査読が要求される
3. 記事が承認されたら、公開される
4. 公開されたブログ記事だけが表示する内容を返すので、未承認の記事は、誤って公開されない

blogクレートに欲しい振る舞いをデモするコードを作成する

```rust:blog/src/lib.rs

pub struct Post {
	state: Option<Box<State>>, // 記事の状態
	pub content: String,       // 記事の内容
}

impl Post {
	pub fn new() -> Post {
		Post {
			state: Some(Box::new(Draft {})), // 初期はDraft
			content: String::new(),          // 初期は空の草稿
		}
	}

	// 記事の内容のテキストを格納する
	// selfへの可変参照を取る公開メソッド
	pub fn add_text(&mut self, text: &str) {
		self.content.push_str(text);
	}

	// 記事の査読を要求すると、状態が変化する
	// Postの現在の状態に対して
	// 内部のrequest_reviewメソッドを呼び出し
	// このメソッドが現在の状態を消費し、新しい状態を返す
	// self.state = self.state.request_review();のようなコードで直接state値の所有権を得るよう設定するのではなく、一時的にNoneにstateをセットする必要がある
	// これにより、新しい状態に変形した後に、Postが古いstate値を使えないことが保証する
	pub fn request_review(&mut self) {
		if let Some(s) = self.state.take() {
			self.state = Some(s.request_review())
		}
	}

	pub fn approve(&mut self) {
		if let Some(s) = self.state.take() {
			self.state = Some(s.approve())
		}
	}
	// Stateのcontentメソッドに委譲する
	// as_refを呼び出すのは値の所有権ではなく、Option内部の値への参照が欲しいから
	// unwrapメソッドを呼び出すが、これは絶対にパニックにならないことが分かっている
	// なぜなら、Postのメソッドが、それらのメソッドが完了した後にstateは常に含んでいることを保証するから
	// これは、コンパイラには理解不能であるものの、None値が絶対にありえないとわかる「コンパイラよりも情報を握っている場合」の一例

	pub fn content(&self) -> &str {
		self.state.as_ref().unwrap().content(&self)
	}
}

trait State {
	// self: Box<Self> は、型を保持するBoxに対して呼ばれた時のみ、このメソッドが呼ばれる
	// この記法は、Box<Self>の所有権を奪い、古い状態を無効化するので、Postの状態値は、新しい状態に変形できる
	// 古い状態を消費するために、request_reviewメソッドは、状態値の所有権を奪う必要がある
	// ここでPostのstateフィールドのOptionが問題になる
	// takeメソッドを呼び出して、stateファイールドからSome値を取り出し、その箇所にNoneを残す
	// なぜなら、Rustは、構造体に未代入のフィールドを持たせてくれないから
	// これにより、借用するのではなく、Postのstate値をムーブすることができる
	// それから、記事のstate値をこの処理の結果にセットする
	fn request_review(self: Box<Self>) -> Box<State>;

	// contentの振る舞いを変化させる
	fn approve(self: Box<Self>) -> Box<State>;

	// 空の文字列スライスを返す
	// postへの参照を引数として取り、そのpostの一部への参照を返す
	// 返却される参照のライフタイムは、post引数のライフタイムに関連する
	fn content<'a>(&self, post: &'a Post) -> &'a str {
		""
	}
}

// 初期状態
struct Draft {}

// 記事が査読街のときの状態を表す
impl State for Draft {
	fn request_review(self: Box<Self>) -> Box<State> {
		Box::new(PendingReview {})
	}

	fn approve(self: Box<Self>) -> Box<State> {
		self
	}
}

// 保留中の査読
struct PendingReview {}

impl State for PendingReview {
	// 自身を返すのは、すでにPendgingreview状態にある記事の査読を要求したらPendingReview状態にとどまるべきだから(査読中のものを査読しようとするようなもの)
	fn request_review(self: Box<Self>) -> Box<State> {
		self
	}

	fn approve(self: Box<Self>) -> Box<State> {
		Box::new(Published {})
	}
}

//  記事を公開
struct Published {}

impl State for Published {
	fn request_review(self: Box<Self>) -> Box<State> {
		self
	}
	fn approve(self: Box<Self>) -> Box<State> {
		self
	}
	fn content<'a>(&self, post: &'a Post) -> &'a str {
		&post.content
	}
}

#[cfg(test)]
mod tests {
	#[test]
	fn it_works() {
		assert_eq!(2 + 2, 4);
	}
}

```


### ステートパータンの代償

メリット:

ステートパターンを使用した実装は、拡張して機能を増やすことが用意

デメリット:

状態が状態間の遷移を実装しているので、状態の一部が密に結合した状態になってしまう
PendingReviewとPublishedの間に、Scheduledのような別の状態を追加したら、代わりにPendingReviewのコードをScheduledに遷移するように変更しなければならない
状態が追加されてもPendingRreviewを変更する必要がなければ作業は減るが、そうすれば別のデザインパターンに切り替えることになる

ロジックの一部を重複させてしまう
重複を除くためには、Stateトレイとのrequest_reviewとapproveメソッドにselfを返すデフォルト実装を試みる可能性がある
これは、オブジェクトの安全性を侵害する
なぜなら具体的なselfが何なのかトレイトには知りようがないから
Stateをトレイトオブジェクトとして使用できるようにしたいので、メソッドにはオブジェクト安全になってもらう必要がある



# パターンとマッチング

パターンは、複雑であれ、単純であれ、Rustで型の構造に一致する特別な記法
match式や他の構文と組み合わせてパターンを使用すると、プログラムの制御フローをよりコントロールできる

以下を組み合わせてパターンをつくる

- リテラル
- 分配された配列、enum,構造体, タプル
- 変数
- ワイルドカード
- プレースホルダー

これらの要素が取り組んでいるデータの形を説明し、それから値に対してマッチングを行い、プログラムに正しい値が合って特定のコードを実行し続けられるかどうかを決定する


## match

```rust
match VALUE {
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
}
```

コンパイル前にmatch式の値の可能性が全て考慮されていなければならない
全可能性をカバーしていると保証する１つの手段は、最後のアームに包括的なパターンを入れること
_という特定のパターンは何にでもマッチするが、変数には束縛されないので、よく最後のマッチアームに使用される


## if let

if let, else if, else if let 式を混ぜてマッチさせることもできる

```rust
fn main() {
    let favorite_color: Option<&str> = None;
    let is_tuesday = false;
    let age: Result<u8, _> = "34".parse();

    if let Some(color) = favorite_color {
        // あなたのお気に入りの色、{}を背景色に使用します
        println!("Using your favorite color, {}, as the background", color);
    } else if is_tuesday {
        // 火曜日は緑の日！
        println!("Tuesday is green day!");
    } else if let Ok(age) = age {
        if age > 30 {
            // 紫を背景色に使用します
            println!("Using purple as the background color");
        } else {
            // オレンジを背景色に使用します
            println!("Using orange as the background color");
        }
    } else {
        // 青を背景色に使用します
        println!("Using blue as the background color");
    }
}
```

if let 式を使うことの欠点は、コンパイラが網羅性を確認してくれない
一方でmatch式はしてくれる
最後のelseブロックを省略する故に、扱い忘れたケースがあっても、コンパイラはロジックバグの可能性を指摘してくれない



## while let

```rust
fn main() {
	let mut stack = vec![1, 2, 3];
	// Someを返し続ける限り、Whileはループを続ける
	while let Some(top) = stack.pop() {
		println!("{}", top);
	}
}
```


## let

変数名は、ただ特に単純な形態のパターン

```rust
let PATTERN = EXPRESSION;
```


## 関数の引数

関数の引数もパターンにできる

```rust
// 関数シグニチャが引数にパターンを使用している
fn foo(x: i32) {

}
```


## 論駁可能性(パターンが合致しないかどうか)

let x = 5; は論駁不可能
xは何にでも合致し、故に合致に失敗することはありえない

if let と while let は、定義により失敗する可能性を処理することを意図したものなので、論駁可能なパターンのみを受け付ける

条件式の機能は、成功か失敗によって異なる振る舞いをする能力にある

エラーメッセージで見かけた際に対応できるように、論駁可能性の概念に確かに慣れておく必要がある


## パターン記法

```rust
fn main() {
	// リテラルにマッチする
	let x = 1;

	match x {
		1 => println!("one"),
		2 => println!("two"),
		3 => println!("three"),
		_ => println!("anything"),
	}

	// 名前付き変数にマッチする
	let x = Some(5);
	let y = 10;

	match x {
		Some(50) => println!("Got 50"),
		Some(y) => println!("Matched, y = {:?}", y),
		_ => println!("Default case, x = {:?}", x),
	}

	println!("at the end: x = {:?}, y = {:?}", x, y);

	// 複数のパターン
	let x = 1;

	match x {
		1 | 2 => println!("one or two"),
		3 => println!("three"),
		_ => println!("anything"),
	}

	// ...で値の範囲に合致させる
	// 限度値を含む値の範囲にマッチ
	let x = 5;
	match x {
		1...5 => println!("one through five"),
		_ => println!("something else"),
	}

	let x = 'c';

	match x {
		'a'...'j' => println!("early ASCII letter"),
		'k'...'z' => println!("late ASCII letter"),
		_ => println!("something else"),
	}

	// 分配して値を分解する
	// 構造体を、enum,タプル, 参照を分配し, これらの異なる部分を使用することもできる

	struct Point {
		x: i32,
		y: i32,
	}

	let p = Point { x: 0, y: 7 };

	// その２
	let Point { x, y } = p;
	assert_eq!(0, x);
	assert_eq!(7, y);

	let p2 = Point { x: 0, y: 7 };
	// match
	match p2 {
		// x軸上の{}
		Point { x, y: 0 } => println!("On the x axis at {}", x),
		// y軸上の{}
		Point { x: 0, y } => println!("On the y axis at {}", y),
		// どちらの軸でもない
		Point { x, y } => println!("On neigher axis: ({}, {})", x, y),
	}

	// enumを分配する
	enum Message {
		Quit,
		Move { x: i32, y: i32 },
		Write(String),
		ChangeColor(i32, i32, i32),
	}

	// let msg = Message::Quit;
	// let msg = Message::Write(String::from("Pattern Totorial"));
	let msg = Message::ChangeColor(0, 160, 255);

	match msg {
		Message::Quit => {
			// Quit列挙しには分配すべきデータがない
			println!("The Quit variant has no data to destructure.");
		}
		Message::Move { x, y } => {
			println!(
				// x方向に{}, y方向に{}だけ動く
				"Move in the x direction {} and in the y direction {}", x,y	
			);
		}
		//テキストメッセージ: {}
		Message::Write(text) => println!("Text message: {}", text),
		Message::ChangeColor(r, g, b) => {
			println!(
				// 色を赤{}, 緑{}, 青{} に変更
				"Change the color to red {}, green {}, blue {}",
				r,
				g,
				b
			)
		}
	}

	// 参照を分配する
	let points = vec![
		Point { x: 0, y: 0 },
		Point { x: 1, y: 5 },
		Point { x: 10, y: -3 },
	];

	let sum_of_squares: i32 = points.iter().map(|&Point { x, y }| x * x + y * y).sum(); // mapはiterの要素をクロージャでそれぞれ計算して、sumでそれらの計算結果を合計する
	println!("{:?}", sum_of_squares);

	// 構造体とタプルを分配する

	let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 }); // 構造体とタプルをタプルにネストし、全ての基本的な値を取り出している
	println!("feet:{}, inches:{}, x:{}, y{}", feet, inches, x, y);

	// ネストされた_で値の一部を無視する
	let mut setting_value = Some(5);
	let new_setting_value = Some(10);

	// Some内の値を使用する必要がないの時にSome列挙子と合致するパターンでアンダースコアを使用する
	match (setting_value, new_setting_value) {
		(Some(_), Some(_)) => {
			// 既存の値の変更を上書きできません
			println!("Can't overwrite an existing customized value");
		}
		_ => {
			setting_value = new_setting_value;
		}
	}
	// 設定は{:?}です
	println!("setting is {:?}", setting_value);

	// タプルの複数の部分を無視する
	let numbers = (2, 4, 8, 16, 32);

	match numbers {
		(first, _, third, _, fifth) => {
			// 何らかの数値: {}, {}, {}
			println!("Some numbers: {}, {}, {}", first, third, fifth)
		}
	}

	// _で未使用変数(unused variavleの警告をしないようにする)
	let _x = 5; // 警告なし
	let y = 10; // 警告あり
	println!("_x = {}", _x);

	// ..で値の残りの部分を無視する
	struct Point2 {
		x: i32,
		y: i32,
		z: i32,
	}
	let origin = Point2 { x: 0, y: 0, z: 0 };
	match origin {
		Point2 { x, .. } => println!("x is {}", x),
	}

	// refとref mut でパターンに参照を生成する

	// ref を使用して値の所有権がパターンの変数にムーブされないように、参照を生成することに目を向ける
	// 通常、パターンにマッチさせると、パターンで導入された変数は値に束縛される
	// Rustの所有権規則は、その値がmatchなどのパターンを使用しているあらゆる場所にムーブされることを意味する

	let robot_name = Some(String::from("Borts"));
	match robot_name {
		// BAD
		// Some(name) => println!("Found a name: {}", name),
		// nameにrobot_nameの値がムーブされる

		// Ok
		Some(ref name) => println!("Found a name: {}", name),
		None => (),
	}
	// robot nameは: {}
	println!("robot_name is {:?}", robot_name);

	// マッチガートで追加の条件式
	let num = Some(4);
	match num {
		Some(x) if x < 5 => println!("less than five : {}", x),
		Some(x) => println!("{}", x),
		None => (),
	}
	let x = 4;
	let y = false;

	match x {
		// はい
		4 | 5 | 6 if y => println!("yes"),
		// いいえ
		_ => println!("no"),
	}

	// @束縛
	// at演算子により、値を保持する変数を生成するのと同時にその値がパターンに一致するかを調べることができる
	enum Message2 {
		Hello { id: i32 },
	}

	let msg = Message2::Hello { id: 5 };

	match msg {
		Message2::Hello {
			id: id_variable @ 3...7,
		} => {
			// 範囲内のidが見つかりました: {}
			println!("Found an id in range: {}", id_variable)
		}
		Message2::Hello { id: 10...12 } => {
			// 別の範囲内のidが見つかりました
			println!("Found an id in another range")
		}
		Message2::Hello { id } => {
			// それ以外のidが見つかりました
			println!("Found some other id: {}", id)
		}
	}
}
```