RUST事始め：所有権とイミュータブル/ミュータブル(mut)，コピーセマンティクス

### 概要
ちょっとしたツールを作るために，RUSTをやり始めた．RUST初心者の備忘録です．

### 変数宣言のミュータブルとイミュータブル
RUSTでは，一度変数が値に束縛されると変更できない．これをイミュータブルという．

```rust
fn main() {
    let v1 = 1;
    v1 = 2; // コンパイルエラー
}
```
変更するためには，変数宣言時に`mut`をつけて，ミュータブルにする．

```rust
fn main() {
    let mut v1 = 1
    v1 = 2;
    println!("v1 = {}", v1); // -> "v1 = 2"と出力
}
```
このとき，`mut`をつけるのは，**変数の左側**．RUSTは強力な型推論機構を持っているので，変数の型を書かなくても勝手に推論してくれる．でも，書いてもいい．よって，上記に型を書くと

```rust
fn main() {
    let mut v1:i32 = 1
    v1 = 2;
    println!("v1 = {}", v1); // -> "v1 = 2"と出力
}
```
こんな風にかける．ここで，**変数の左側**に書くとは，`let v1:mul i32 = 1;`とは書かない，ということ．これだとコンパイルエラーになる．


### 関数定義のミュータブルとイミュータブル
RUSTでは，変数宣言のときには基本的にコンパイラに型を推論させるため，型は省略するのが普通らしい．逆に，型推論のヒントとして関数の引数には型をきっちり書く．


```rust
fn test(v:i32) {
    println!("v = {}", v);
}

fn main() {
    let v1 = 10;
    test(v1);
}
```
これで，`v=1`と出力される．ここで，`test`の中で`v`の値を書き換えたいとする．しかし，`test`の引数`v`はイミュータブルなので変更できない．そこで，変数宣言(**変数名の前**)に`mut`をつける．

```rust
fn test(mut v:i32) {
    v += 1
    println!("v test = {}", v); // "v = 11"と出力
}

fn main() {
    let mut v1 = 10;
    test(v1);
    println!("v main = {}", v); // "v = 10"と出力
}
```
~~ここで，呼び出し側にも`let mul v1 = 10`と，`mut`をつけなければいけないことに注意する．~~
間違いです．`test`の引数は参照ではないので，呼び出し側に`mut`は不要です(あってもいいです)．
考え方としては，変数の前の`mut`は，その変数(が束縛されている値)が可変かどうかを示すと考えて良いと思います．よって，関数呼び出しで値の所有権をmoveすると，呼び出し元では二度とその変数に触れないので，ミュータブルだろうとイミュータブルだろうと関係ない，ということだと思われます．そして，所有権が移動した先(`test`関数)で，その変数が可変なのかどうかを決める，という感じかと．呼び出し元ではすでにその変数にはアクセスできないので，どちらにしても不具合は起きない，ということになると思います．

そして，このプログラムを実行すると，

```
v test = 11
v main = 10
```

このように，**正常**に動作する．この点にはまだ戻って再考する．

### 参照
説明の都合上，構造体を用意する．

```rust
struct Test {
    iv: i32,    
}
```

```rust
fn t2(mut arg: Test) {
    arg.iv = 5;
    println!("iv : {}", arg.iv);
}

fn stest() {
    let mut sv = Test {  // mutはなくてもOK
        iv: 20,        
    };
    println!("iv : {}", sv.iv);
    t2(sv);    
}
```

`mut`に関しては上記の例と同じなので，これを実行すると

```
iv : 20
iv : 5
```
となる．

ここで，`stest`を以下のように一行加えて書き換える

```rust
fn stest() {
    let mut sv = Test {
        iv: 20,        
    };
    println!("iv : {}", sv.iv);
    t2(sv);    
    println!("iv : {}", sv.iv); // compile error
}
```
コメントのところでコンパイルエラーとなる．先程の例ではコンパイルできていたはず．これに関しては後述する．

この問題の解決には，所有権という考え方が必要になる．このあたりの説明はたくさんあるだろうから，結論だけ書くと，所有権を渡さずに借用を使え，ということになる．馴染みやすい言い方だと，参照を使え，ということになる．

参照を使った関数定義を，イミュータブルの場合，ミュータブルの場合それぞれ示す．

```rust
// イミュータブル
fn t3(v:&Test){
    println!("iv t3 = {}", v.iv)
}
// ミュータブル
//fn t4(mut v:&mut Test){ // これでもいい
fn t4(v:&mut Test){
    v.iv += 1;
    println!("iv t4 = {}", v.iv)
}
```
参照を使うときには，関数の引数の型の前に'&'をつけることで表現する．また，ミュータブルのときには**型の前**に`&mut`をつける．参照を使わないときは**変数の前**に付けていた．こうすると，変数の前には何もつけなくて良い(`&mut`の場合にはつけてもいい)．
考え方としては，型の指定によってこの型，`&mut Test`でミュータブルの参照型である，ことが確定している．よって，変数宣言に`mut`がなくてもミュータブルだとわかるから省略可能，と理解すればいい(?)
これは結局，

```rust
let mut hoge = 20;
let abc = &mut hoge;
```
と同じことをやっている．型をきちんと書くと
```rust
let mut hoge: i32 = 20;
let abc: &mut i32 = &mut hoge;
```
となり，`let mut abc`と書かなくても`abc`はミュータブルだとわかる，ってこと


```rust
fn stest() {
    let mut sv = Test {
        iv: 20,        
    };

    println!("iv : {}", sv.iv);

    t3(&sv); // 参照を渡す
    println!("iv : {}", sv.iv); // コンパイルできる    
}
```
今度は，`t3`の呼び出しで参照を渡している(svの前に`&`をつけてる)．こうすると，コンパイルエラーとならない．
実行すると

```
iv t3 = 20
iv : 20
```

を得る．また，ミュータブルの関数定義も同様で，**型の前**に`&mut`をつけることに注意する．

```rust
fn stest() {
    let mut sv = Test {
        iv: 20,        
    };
    println!("iv : {}", sv.iv);
    t4(&mut sv); // t4の引数が&mut Testなので，&だけではなく，&mutとしなければならない
    println!("iv : {}", sv.iv);    
}
```
t4を呼び出すと，以下の結果を得る．

```
iv t4 = 21
iv : 21
```
t4の中でivの値が1加えられたことにより，stestの出力も変わっている．
ここで，関数定義の仕方をまとめると，以下のようになる．

```rust
fn f(v:&Test) {}
fn f(v:&mut Test) {}
//fn f(v:mut Test) {} // NG
fn f(v: Test) {}
fn f(mut v: Test) {}
//fn f(&mut v: Test) {} // NG
```

つまり，参照型を使うかどうかで`mul`を付ける位置が変わることに注意する．初心者の混乱の元．．

### 所有権
RUSTには，所有権，という概念があり，変数や値の所有権を放棄したあと，その変数にアクセスすることができない．そして，所有権の移動は変数の代入等によって起こる．

```rust
t2(sv);
println!("iv : {}", sv.iv); // compile error
```
そのため，関数呼び出しの時，`t2(sv)`ここで`sv`の所有権を放棄したことになる．その後，`sv.iv`で構造体にアクセスしようとしているのでコンパイルエラーになった．しかし，`i32`の場合にはコンパイルでき，`Test`の場合にはコンパイルエラーとなった，なぜ振る舞いが違うのかを理解するには，次に述べるコピーセマンティクスを理解する必要がある．

### コピーセマンティクス
i32でコンパイルできた時の実行結果をみると

```
v test = 11
v main = 10
```
となっている．つまり，test関数の中のvと，mainのvは別のものとして扱われている．しかし，Testでは別のものと扱われず，所有権を放棄したためにコンパイルエラーとなっていた．なぜこんな違いが出るかと言うと，**代入文の意味(セマンティクス)**が異なるからである．i32の時，代入文とは値のコピーであり，Testのときには所有権の移動，である．RUSTの基本は後者だが，意味を変えてコピーにする方法がある．詳しい説明は他に譲るが(というか，そこまで詳しくない)，Copyトレイト，Cloneトレイトを実装することでこのセマンティクスを変更することができる．
具体的には，Testの定義にアノテーションを加える．

```rust
#[derive(Copy, Clone)]
struct Test {
    iv: i32,    
}

fn t2(mut arg: Test) {
    arg.iv = 5;
    println!("iv : {}", arg.iv);
}

fn stest() {
    let mut sv = Test {
        iv: 20,        
    };
    println!("iv : {}", sv.iv);
    t2(sv);
    println!("iv : {}", sv.iv); // compile OK
    
}
```

こうすると，このコードは無事にコンパイルでき，以下の実行結果を得る．

```
iv : 20
iv : 5
iv : 20
```
今度は，代入の意味がコピーに変わった，ということがわかる．ではなぜi32のときには最初からこのような振る舞いだったのか，といえば，RUSTではプリミティブ型は予めCopyとCloneトレイトを実装している，からである．紛らわしい．．．

しかし，これはJavaなどの言語がプリミティブ型とオブジェクト型でコピーセマンティクスと参照セマンティクスを使い分けているのと同じなので，自然なのかな？とも思う．

間違いなどあればご指摘ください