【Rust】変数でパニックになったのでメモ。借用って…

なんとなくRustが気になって触ってたら**借用(borrow)** とか**所有権(ownership)** とか**参照(references)** とか**ムーブ(move)** とか**可変(mutable)** とか**不変(immutable)** とか、参照はともかく他の言葉はなじみがない。メモを残すしかない。

# 可変と不変
Rustで変数宣言をするときは**let**を使い宣言する。型を指定しなくても大丈夫。型指定する場合には変数名に続けて **: 型** を指定する。

```rust:
//変数宣言
let val = 1;

//型指定して変数宣言
let val: i32 = 1;
```
C言語やJava言語のように型を先に指定しないことや、型名に驚くが気にしない。

## 不変 immutable
これに驚いた。変数は基本的に**不変**。変数なのに！？
どうやらRustでは不変が基本。これは**定数(constant)** とは異なる。

```rust:
//変数宣言
let val = 1;

//...

val = 2;     // <-- これはNG：valは不変であり変化しない。
```
もし、valの値を変えたいなら以下のように再宣言し直すことで解消出来る。

```rust:
//変数宣言
let val = 1;

//...

let val = 2;     // <-- これはOK
```
**同じ名前の変数を宣言してはいけない** と言われ、教えてきた身からすると不思議な感覚だった。

## 可変 mutable
可変な変数を宣言するには**mut**を変数宣言時に使う必要がある。

```rust
//可変な変数宣言
let mut val = 1;
val = 2;     // <-- これはOK：valは可変な変数であり変化する。
```

# 所有権とムーブ
どうやらRustの変数には**所有権**という考え方があるらしい。

## 所有権 ownership
まず、Rustの変数は**値に対する所有権**を持っている。

```rust
let val1 = 1;
```
上記のプログラムでは変数val1は値「1」に対する所有権を持つことになる。
```rust
let val1 = 1;
let val2 = val1;
```
上記プログラムでは変数val2はval1の値「1」が複製され、新たな「1」に対して所有権を持つことになる。値自体は同じ「1」でも、メモリ上は異なった存在。

基本データ型(primitives)の値は、他の言語と大きく異なり点もなく悩む必要が無い。

しかし、それ以外の型では少々複雑な動きを見せる。
例えばString型のデータを扱う場合が例に挙げられる。
以下記述によってString型のデータを生成する事が出来る。

```rust
//変数string_value1にString型の「hello」が格納れる。
let string_value1 = String::from("hello");
println!("string_value1 is {}", string_value1);
```

この記述に一行追加すると、エラーになる。

```rust
//変数string_value1にString型の「hello」が格納れる。
let string_value1 = String::from("hello");
let string_value2 = string_value1;           //<-- これを追加
println!("string_value1 is {}", string_value1);

// > error[E0382]: borrow of moved value: `string_value1`
```

一見、問題無く動きそうな記述だがエラーになる。
これは**所有権**の考え方が絡んでいるため。`let string_value2 = string_value1;`という記述は、**所有権の移動**となる。
要するにstring_value1が所有していたString型のデータに対する権利を、string_value2に渡してしまうことになり、string_value1は所有権を持たない状態になる。その為、エラーとなってしまう。この所有権の移動を**ムーブ**と呼ぶ。

## Stringと&str
*ここは一旦メモ*
* &strは基本型。不変。長さ固定。

# 借用 borrow
所有権はメモリをより安全に効率的に扱う事が出来る仕組み。所有権をなんとなくイメージできれば借用は大した話ではなかった。言葉の通り**一時的に所有権を渡して、処理が終わったら返してもらう**という様な感じで使いたいだけのこと。(実際には所有権は渡さない)
これは関数の話で説明されていて、引数として変数を与えたときに重要な考え方。
以下のプログラムは引数を使った関数の例。

```rust
fn main(){

    let mut string_value = String::from("hello");
    string_print(string_value);      //<--ここで関数の呼びだし。引数を与えている。

}

fn string_print( val: String){
    println!("val is {}", val);
}

//output >>val is hello
```
このプログラムは問題なく動くが、次のように改変すると動かなくなる。

```rust
fn main(){

    let mut string_value = String::from("hello");
    string_print(string_value);
    string_print(string_value);      //<--ここで同じ関数を同じ引数で呼びだし。エラーになる。

}

fn string_print( val: String){
    println!("val is {}", val);
}

//output >>error[E0382]: use of moved value: `string_value`
```
実際はもっと詳細な情報が出るがコンパイルすると`error[E0382]: use of moved value: string_value`になる。要するに**既にムーブしたstring_valueを使っている**という指摘。**引数として変数を指定しても所有権のムーブは発生する**ということ。関数の引数に変数を渡した場合、所有権が移ってしまうため続けて利用する事が出来ないということになる。これを解決するには戻り値を利用する方法がある。

```rust
fn main(){

    let mut string_value = String::from("hello");
    string_value = string_print(string_value);
    string_value = string_print(string_value);

}

fn string_print( val: String) -> String{
    println!("val is {}", val);
    return val;      // <-- 引数で受けとった値を、呼びだし元に返す
}
```
引数で渡した値を関数から返してもらえば解決する。だが、手間。ここで登場するのが**借用**。
一時的に所有権ごと貸し出し、利用後に返してもらうイメージ。以下のような記述になる。
```rust
fn main(){

    let mut string_value = String::from("hello");
    string_print(&string_value);     // <-- 引数に「&」が付加されている
    string_print(&string_value);

}

fn string_print( val: &String){     // <-- 引数に「&」が付加されている
    println!("val is {}", val);
}
```
要は**参照**のこと。所有権を渡してしまうと問題があるのでオブジェクトに対する参照を引数として渡す。所有権はstring_valueが保持し続けている。**関数の引数に所有権の代わりに参照を渡すこと**を借用と呼んでいる。
ただし、このままでは所有権は持っていないため関数内で値に変更を加えることは出来ない。**可変可能な参照**は次のように記述する。
```rust
fn main(){

    let mut string_value = String::from("hello");
    add_world(&mut string_value);     // <-- 引数に「&mut」が付加されている。可変可能な参照を渡す。
    string_print(&string_value);

}

fn add_world( val: &mut String){     // <-- 引数に「&mut」が付加されている
    val.push_str(" world");
}

fn string_print( val: &String){
    println!("val is {}", val);
}
```

# 最後に
RustはGC(ガーベジコレクション)を持たない言語でありながら、メモリを安全に扱える言語らしい。確かにC言語を勉強していたときのようにメモリの確保とか解放とか意識せずに書ける。逆にJava等のようにGCに任せて勝手に解放されるのも良いが、Rustはいつメモリが解放されるのか(所有権を保持した変数のスコープが終了した時)が明確。安全に使えてる気がしてきた。いずれにしても、Rustは所有権って考えを整理しておかないとダメだと思った。

なんとなく見かけて触り始めたRustです。このメモにも間違いはあるかもしれませんが少しでも参考になればと思います。