[Rust] チュートリアル① 所有権〜構造体、Enumまで

# はじめに
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の思想を感じ取ることができる


# 束縛 (binding)

Rustを学んでいると、いたるところで束縛がでてくる

束縛とは、変数名や関数名などを実体と結びつけること
束縛には、静的束縛と動的束縛とがある

静的束縛

- コンパイル時に分かっている
- スタックに保存される
- プリミティブ値など

動的束縛

- 実行してみないと分かっていない
- ヒープに保存される
- プリミティブ値以外


#  所有権


## 所有権規則

- Rustの各値は、所有者と呼ばれる変数と対応している
- いかなる時も所有者は１つ
- 所有者がスコープから外れたら、値は放棄される


## 変数スコープ

- 未初期化の値は使えない
- 束縛をムーブした後ではそれを使うことが出来ない(プリミティブ型を除く)

let v = vec![1,2,3];
let v2 = v;

1. 最初の行はベクタオブジェクト v とそれを含むデータのためのメモリを割り当てる
2. ベクタオブジェクトはスタックに保存され、ヒープに保存された内容([1,2,3])へのポインタを含む
3. v を v2 にムーブするとき、それは v2 のためにその v1 のポインタのコピーを作る
4. この時点で、ヒープ上のベクタの内容へのポインタが２つあることを意味する これはデータ競合を持ち込むことで Rust の安全性保証に違反する そのため、Rust はムーブを終えた後の v の仕様を禁止する

- すべてのプリミティブ型は copy トレイトを実装している
- copy トレイトを実装していない方を使っていたならば、ムーブした値を使おうとしたため、コンパイルエラーがでる
- トレイトとはある型が提供しなければならない機能を Rust コンパイラに伝える言語機能(ある型の追加機能)

- 参照は束縛と同じでイミュータブルなので参照元を変更することはできない
- &mut 参照をつかうことで「ミュータブルな参照」によって借用しているリソースを変更することができる


```rust
let mut x = 5;
{
	let y = &mut x; // &mut 借用がここから始まり
	*y += 1; // ↓
} // ここで終わる
println!("{}", x);
```


- \*y は y が&mut 参照の意味
- これ以外は、&mut は普通の参照と同じ


## メモリと確保


### メモリに対する苦悩　(Rustは違う)

ガベージコレクタ(GC)付きの言語では、GCが使用されないメモリを検知して片付けるため、プログラマは、そのことを考慮する必要はない

GCがないなら、不要なメモリを返還する責任がプログラマにある

メモリ解放を忘れればメモリを無駄にする
タイミングが早すぎたら呼び出しエラーになる
解放したメモリを解放しようとすればバグになる
allocateとfreeは完璧に対にならなければならない


### Rustのメモリ管理方法

メモリを所有している変数がスコープを抜ければ、メモリは自動的に変換される

主に所有権を考えのことを考えていれば、メモリのことはくよくよ悩まずに済む

変数がスコープを抜けたら、Rustは自動的にdrop関数を呼び出し、その関数が使ったヒープメモリを片付ける


## 借用

1. 借用はすべての所有者のスコープより長く存続してはならない。
2. ２種類の借用のどちらか１つを持つことはあるが、両方を同時に持つことはない

- リソースに対する１つ以上の参照( &T )
- ただ１つのミュータブルな参照( &mut T )



## 「データ競合の定義」との違い


### 参照

データ競合は２つ以上のポインタがメモリの同じ場所に同時にアクセスするとき
少なくともそれらの１つが書き込みを行っていて
作業が同期されていないところでデータ競合は起こる

`書き込みを行わない(immutableな参照)のであれば、参照はいくらでももつことが出来る`

```rust

let mut x = 5;
let a = &x;
let b = &x;
let c = &x;
let c = &x;
let e = &x;
let f = &x;
let g = &x;
let h = &x;
let i = &x;

let z = &mut; // NG

```


#### mutな参照

どちらか１つは可能であるが、以下、２つ同時にもつことは出来ない

- リソースに対する1つ以上の参照（&T）
- ただ1つのミュータブルな参照（&mut T）

これが、Rust がデータ競合をコンパイル時に回避する方法

```rust:OK

let mut x = 5;
let y = &mut x; // ただ１つのミュータブルな参照(&mut T)

```

```rust:NO

let mut x = 5;
let y = &mut x; // &T
let z = &mut x; // &mut T

```


## コピー

コピーには、shallow copy(浅いコピー)、deep copy(深いコピー) 

データは３つの要素をもつ構造体で表現される

1. メモリの領域を示すポインタ
2. 容量
3. 長さ


### shallow copy

- プリミティブ値はそのままコピーする、それ以外は参照をコピーする
- メモリ上のバイト列を単純にコピーする操作、Cの`memcopy`に相当する


### deep copy 

- 同じ場所を参照するのでは困る、という場合に使う
- 参照先のデータも含めて別のメモリ領域に複製するコピー方法
- プリミティブ値だけでなく、オブジェクトも値としてコピーする
- Copyトレイトを実装した型で行われる値のコピーと、Cloneトレイトを実装した型で行われる値のclone()は多くの場合は異なる操作になる
- ヒープデータが実際にコピーされるので、所有権はムーブしないので、コピー元を呼び出してもOK

fn main() {
	let mut s = String::from("hello");
	let mut s2 = s.clone();

	println!("push前");

	println!("{}", s);
	println!("{}", s2);

	println!("push後");

	s.push_str(",world");
	s2.push_str(" ketty");

	println!("{}", s);
	println!("{}", s2);
}

#### プリミティブな値はcloneしなくても、デフォルトでdeep copyできる

```rust

fn main() {
	let s = String::from("hello");
	let s2 = s; // 所有権がムーブ
	println!("{}", s); // NG
	println!("{}", s2);
	let x = 5;
	let y = x; // deep copy
	println!("{}", x); // OK
	println!("{}", y);
}


// [output]
push前
hello
hello
push後
hello,world
hello kettyut]
```



### ムーブセマンティクスとコピーセマンティクス

Rustのデフォルトはムーブセマン ティクス(所有権が移動する)

コピーセマンティクスは変数束縛のたびに値がコピーされる(所有権は変わらない)

- Copyトレイトを実装している(プリミティブ値など)は、束縛時にコピーセマンティクスとなる



### スコープの考え方

ュータブルな借用はイミュータブルな借用を作る前にスコープから外れる
ス i コープは借用がどれくらい存続するのか理解するための鍵になる

```rust
let mut x = 5;

{
	let y = &mut x; // -+ &mut 借用がここから始まる
	*y += 1; // |
} // -+ ... そしてここで終わる

println!("{}", x); // <- ここで x を借用しようとする

let mut v = vec![1, 2, 3];
v[0] = 5; // ここは ok
v.push(25); // ここは ok

for i in &v {
	println!("{}", i);
	v[0] = 5;  // ここはNG
	v.push(25);  // ここはNG
}
```


### 解放後の使用

スコープ内での参照は、スコープ外で使用出来ない

```rust
let y: &i32;
{
	let x = 5;
	y = &x;
}

println!("{}", y);
```





# スライス

let s = "hello";  
let bytes = s.as_bytes();  // 文字列をバイト列に変換
for (i, &item) in bytes.iter().enumerate() {}

iterは、コレクションの各要素を返すメソッド
enumerateがiterの結果を包んで、分かりにタプルの一部として各要素を返す
enumerateが返すタプルの第１要素は添字、第２要素はコレクションの要素への参照





# 構造体

一般的なプログラミング言語と同様に各データ辺に名前をつけるので、値の意味が明確になる

```rust
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}
```

## 構造体のインスタンスを生成する

```rust

    // ミュータブルなインスタンス
	let mut user1 = User {
		email: String::from("someone@example.com"),
		username: String::from("someusername123"),
		active: true,
		sign_in_count: 1,
	};

	// フィールドの値を変更できる
	user1.email = String::from("anotheremail@example.com");


## 他のインスタンスからインスタンスを生成する

let user2 = User {
	email: user1.email,
	username: user1.username,
	active: user1.active,
	sign_in_count: user1.sign_in_count,
};
```


## 異なる型を生成する名前付きフィールドのないタプル構造体を使用する

フィールドに紐付けられた名前は不要な場合
フィールドの型のみを必要とする場合に有用

```
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
```

## タプルでリファクタリングする

```rust
// 正方形の面積をもとめる関数を何も考えずに作成すると次のようになる

fn area(width: u32, height: u32) -> u32 {}

//２つの引数は相互に関係があるので、引数をタプルにして括る

fn area(dimensions: (u32, u32)) -> u32 {
	dimensions.0 * dimensions.1
}
```


## より意味づけする

構造体でデータにラベル付けして意味付けをしたものを引数につかう

型は構造体インスタンスの不変借用

ただの借用だと、最初のインスタンスでムーブするので、同一スコープで１つしかインスタンスが作成できない

```rust
struct Rectangele {
	width: u32,
	height: u32,
}

// 不変借用で複数のインスタンスを作成可能
fn area(rectangle: &Rectangle) -> u32 {
	rectangle.width * rectangle.height
}
```


## デバッグ

println!マクロのデフォルトでは構造体の中身を確認することができない

```rust
#[derive(Debug)] をコードに追記して
println!({})の{}内に:?をもしくは:#?を追加する

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };

    println!("rect1 is {:?}", rect1);
}

// [output]
rect1 is Rectangle { width: 30, height: 50 }
```


## メソッド記法

構造体インスタンスを引数に取る関数を作ることができる

Rectangleの文脈内で関数を定義するには、impl(implementation; 実装)ブロックに、構造体名と同名にする

`&self → rectangle: &Rectagleの代わり`

```rust
struct Rectangle {
	width: u32,
	height: u32,
}

impl Rectagle {
	fn area(&self) -> u32 {  
		self.width * self.height
	}
}

fn main() {
	let rect1 = Rectangle {width: 30, height: 50};
}
```


## 演算子はどこに行った?

C/C++では、objectポインタならobject->something()となる

Rustには->演算子の代わりとなるようなものはない

その代わりに、自動参照および参照外しという機能がある
Rustにおいてメソッド呼び出しは、この動作が行われる数少ない箇所

object.something()とメソッドを呼び出すと、コンパイラはobjectがメソッドのシグネチャと合致するように、自動で&か&mutか*を付与する

以下、コードは同じ
p1.distance(&p2);
(&p1).distance(&p2);

メソッドには自明な受けて(selfの型)がいるので、この自動参照機能は動作する

受け手とメソッド名が与えられれば、コンパイラは確実にメソッドが読み込み専用(&self)か、書き込みもするか(&mut self)のか、所有権を奪う(self)のか判断できる


## 複数のimplブロック

各構造体には、複数のimplブロックを存在させることができる

```rust
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
```


# Enumとパターンマッチング

## Enum

列挙型は、enumとも称される

取りうる値を列挙することで、型を定義させてくれる
つまり、プログラムにデータ以上の情報をコード化できるということ

IPアドレスをバージョン別で表したい時

// IpAddrKindはコードの他の場所でも使用できる独自のデータ型

```rust
enum IpAddrKind {
	V4,
	V6,
}
```


## Enumの値

enumの各列挙しにデータを直接添付することができる

```rust
enum IpAdrr {
	V4(u8,u8,u8,u8),
	V6(String),
}

let home = IpAddr::V4(127,0,0,1);
let loopback = IpAddr::V6(String::from("::1"));

// 幅広い種類の方を列挙子に埋め込むことができる

enum Message {
	Quit, // 紐付けられたデータなし
	Move { x: i32, y: i32 }, // 匿名構造体を含む
	Write(String), // 単独のStringオブジェクト
	ChangeColor(i32, i32, i32), // 3つのi32値
}

// structであっても、enumの列挙子が保持しているのと同じデータを格納可能

struct QuitMessage; // ユニット構造体
struct MoveMessage {
    x: i32,
    y: i32,
}
struct WriteMessage(String); // タプル構造体

// enumは、各々それ自身の型が違っていても、共通機能が何なのか明確なのでわかりやすい

// impleブロックでenumにもメソッドを定義できる

impl Message {
	fn call(&self) {
		// メソッド内容
	}
}
```


## RustにNullを実装する

RustにはNullが存在しないが、enumのOption<T>でNullの概念をコードがすることができる

```rust
enum Option<T> {
	Some(T), // 存在する
	None, // 存在しない
}
```


## matchフロー演算子

一連のパターンに対して値を比較し、マッチしたパターンに応じてコードを実行させる

パターンは、リテラル値、変数名、ワイルドカードやその他多数のもので構成することができる

```rust
enum UsState {
	Alabama,
	Alaska,
}

enum Coin {
	Penny,
	Nickel,
	Dime,
	Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u32 {
	match coin {
		Coin::Penny => 1,
		Coin::Nickel => 5,
		Coin::Dime => 10,
		Coin::Quarter(state) => {
			println!("State quatre from {:?}?", state);
			25
		}
	}
}

fn main() {
	let value = value_in_cents(Coin::Quarter(UsState::Alabama));
	println!("{}", value);
}
```

## _ というプレースホルダー

全ての可能性を列挙したくない時に使用するのが_

```rust
match some_u8_value {
    1 => println!("one"),
    3 => println!("three"),
    5 => println!("five"),
    7 => println!("seven"),
    _ => (),
}
```

## if let で簡潔なフロー制御

if let 記法でifとletをより冗長性の少ない方法でパターンマッチを行う

if let は値が１つのパターンにマッチした時にコードを走らせ、他は無視するmatchへの糖衣構文(シンプルにしたもの)

```rust
// 冗長なコード
let some_u8_value = Some(3);
	match some_u8_value {
		Some(3) => println!("three"),
		_ => (),
	}

// if let記法
if let Some(3) = some_u8_value {
	println!("three");
}
```


## if let else

```rust
let mut count = 0;
if let Coin;:quarte(state) = coin {
	println!("State quarter from {:?}!", state);
} else {
	count += 1;
}
```