Rustの所有権に親しむ

遅れてしまいましたが、これは [Rust その2 Advent Calendar 2016](http://qiita.com/advent-calendar/2016/rust-lang-2) の 5日目の記事です。

この記事はRustをあまり知らない人でも理解できると思います。

Rustを学んで所有権の仕組みに感動したので、
自分の理解の確認を兼ねて所有権のポイントをまとめました。
また、所有権によって得られるメリットを二つ、所有権の魅力として書いて見ました。

# 所有権の原則
RustはGCなし（ゼロコスト）でリソースを自動的に解放する仕組みを持っていて、それを実現する概念が所有権です。
Rustでは変数(束縛)がスコープを抜けるとき、リソースが解放されます。
スコープを抜けた時に全てのリソースが解放されなくてはいけないので、
変数に対する参照がある場合も、参照は参照元のスコープより長く存続できません。

# 3つのポイントで所有権を理解する
上記の原則を前提として、実際にプログラミングするときには
次の3つを意識すれば「借用チェッカとの争い」をしなくて済みそうです。

1. 変数を束縛(代入)すると元の変数はアクセスできなくなる
2. 参照は幾つでも作れる
3. mutableは一つだけ

```rust:1.変数を束縛(代入)すると元の変数はアクセスできなくなる
let v1 = vec![1, 2, 3];
let v2 = v1;
println!("Hello, {}!", v1[1]); // error[E0382]: use of moved value: `v1`
```
```rust:2.参照は幾つでも作れる
let v1 = vec![1, 2, 3];
let v2 = &v1; // 代入時に&をつけると参照になります
let v3 = &v2;
println!("Hello, {}, {}, {} !", v1[0], v2[1], v3[2]); // no error
```
```rust:3.mutableは一つだけ
let mut v1 = vec![1, 2, 3];
let mut v2 = &mut v1; // &mutをつけるとmutable参照になり書き込みできます。
let mut v3 = &mut v1; // error[E0499]: cannot borrow `v1` as mutable more than once at a time
```
```rust:3'既に参照のある変数からはmutable参照できない
let mut v1 = vec![1, 2, 3];
let mut v2 = &mut v1; //no error
let v3 = &v1; //error[E0502]: cannot borrow `v1` as immutable because it is also borrowed as mutable
```
```rust:3''順番を入れ替えてもダメ(参照を既に持っているとmutable参照できない)
let mut v1 = vec![1, 2, 3];
let v3 = &v1; //no error
let mut v2 = &mut v1; //error[E0502]: cannot borrow `v1` as mutable because it is also borrowed as immutable
```
```rust:3'''mutable参照から通常の参照は作れるが、mutable参照に書き込みできなくなる
let mut v1 = vec![1, 2, 3];
let mut v2 = &mut v1;
let v3 = &v2; //no error
*v2 = vec![1, 5, 3]; //error[E0506]: cannot assign to `*v2` because it is borrowed
```
```rust:3''''もちろんスコープを抜ければ書き込める
let mut v1 = vec![1, 2, 3];
let mut v2 = &mut v1;
{
    let v3 = &v2; //no error
}
*v2 = vec![1, 5, 3]; //no error
```
 
# 所有権の魅力
## 変数のスコープを小さくする作用がある
束縛のデフォルトの動作は、束縛された変数に以後アクセスできなくなるという、ユニークで面倒くさいルールですが、
このルールは変数のスコープやメソッドの長さを小さく保つようにプログラマーに作用し、コードを綺麗にする効果があると思います。

## 不変と可変の使い分けがとても楽
mutの有無で変数自体への書き込みを制御するだけではなく、
変数にセットされたインスタンス変数(structのデータ)への書き込みも同時に制御できます。

```rust:驚きの機能。でもエラーメッセージはわかりにくい。
let mut mutable_vector: Vec<i32> = (0..10).collect();
mutable_vector.push(0); // no error

let imutable_vector: Vec<i32> = (0..10).collect();
imutable_vector.push(0); // error: cannot borrow immutable local variable `imutable_vector` as mutable
```
これは所有権とメソッド構文の合わせ技で実現しています。

```rust:Vec.push()の実装
pub fn push(&mut self, value: T) {
    // This will panic or abort if we would allocate > isize::MAX bytes
    // or if the length increment would overflow for zero-sized types.
    if self.len == self.buf.cap() {
        self.buf.double();
    }
    unsafe {
        let end = self.as_mut_ptr().offset(self.len as isize);
        ptr::write(end, value);
        self.len += 1;
    }
}
```
Rustはメソッドからインスタンス変数(structのデータ)への直接参照がありません。
自身のメンバ変数へアクセスする関数は第一引数で参照($selfや&mut self)を受け取るように定義します。
ただし関数を呼び出す時は第一引数を省略して「変数名.関数名(第二引数)」と書きます。

こう考えると、mutを外すとpushできなくなることも、「cannot borrow immutable local variable」と言われることも納得できます。

また、不変オブジェクトの全ての内部データが不変であることも確実に保証されることにもなります。
JavaやScalaでは不変と可変のオブジェクト変換は手間もコストもかかるので、この仕組みには感動しました。


# おわり
Rustの所有権システム良いですね。