C++erのためのRust入門(未完)

新しい言語を勉強したかったので、Rustを始めてみる。
# Rustを選んだ理由
候補言語としては、*D*, *Go*, *Rust*があった。
そのうちで*Rust*を選んだのは次のような理由からだった。

- **演算子オーバーロードが使いたかった**
*Go*には演算子オーバーロードがない  
  
- **ジェネリクス(テンプレート?)が欲しかった**
*Go*にはジェネリクスがないらしい  
  
- **ガーベッジコレクタ(GC)が気に入らない**
*Go*も*D*もGCをオフにすることはできるらしいが、たぶん普通のことではないだろう
  
念の為に言っておくと、*Go*と*D*には何の非もない。
私が大きな変化についていけないだけのことである。

# Rustのリリースの種類
- **Nightly** masterブランチの日ごとの最終成功ビルド、新機能が追加される。
- **Beta** 6週ごとにNightlyから昇格、Stableに向けてバグフィックスが行われる。
- **Stable** 6週経ったBetaが昇格。

# macOSにおけるRustのインストール方法
1. Homebrewを使う (stableのみ)  
`brew install rust`で入れられる。
2. rustupを使う  
`curl https://sh.rustup.rs -sSf | sh`で入れられる。  
(URLが変わっている可能性もあるので[www.rustup.rs](https://www.rustup.rs/)を確認すること)

# Rustの書き方
## Rustの資料
以下全て英語。日本語訳も探せばあるかも。

- [The Rust Programming Language(TRPL)](https://doc.rust-lang.org/1.30.0/book/first-edition/)  
Rustの教科書。これを読めばまともなコードが書ける。
- [Rust By Example(RBE)](https://rustbyexample.com/)  
説明よりコードを読むほうが好きな人に。TRPLのお供にもどうぞ。
- [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/basics.html)  
具体的な処理の書き方を学びたい方へ。あんまり読んでない。
- [The Rustnomicon](https://doc.rust-lang.org/nomicon/)  
Rustを安全性の軛から解き放つ`unsafe`のこと、またメモリレイアウト、FFIの書き方などが載っているはず。読んでない。
- [The Rust Reference](https://doc.rust-lang.org/reference/)  
Rustの仕様書を目指して書かれている文書。言語自体が発展途上なのでどうしても内容は古くなりがちだが役に立つ。ちょっと読んだ。
- [Rust Language Cheat Sheet](https://cheats.rs/)  
Rustの文法のチートシート。他言語にすでに習熟している人がRustを学ぶならこちらに先に目を通したほうがいいかもしれない

この記事は基本的にTRPLに添ってすすめる。
ただし、まとめたほうがいいと思ったものは適当に再構成する。

## コメント
```rust
// 行コメント

/* 
ブロックコメント
    /*
    ネストも可
    */
*/

/// ドキュメントコメント
/// 内部でMarkdownが使えるらしい

//! ドキュメントコメントその2
//! こちらは個々の関数等よりは、モジュール全体の説明などに使うらしい
```

## 変数の型
- ブール型
- 整数型 (`u8,u16,u32,u64,i8,i32,i64`)
- 浮動小数点数型 (`f32,f64`)
- 実装依存の整数型 (`usize,isize`)  
(大きさはそのプラットフォームのポインタ型と同じ)
- 32ビット文字型
- 8ビット文字列型
- タプル型
- 配列型とスライス型
- 構造体型
- enum型
- 関数ポインタ型

カッコ内はリテラルに付けられる接尾辞。

## 変数宣言
Rustでは、変数はデフォルトで不変(定数)で、変更できるようにするには`mut`をつける。
現代の言語らしく型推論もあるのでよい。

```rust
let a = 1;     // 定数
let mut b = 3; // 定数でない
let c: i32 = 0; // 型指定
```

変数の宣言と初期化は分けることができる。
分けた場合でも型推論ははたらく。

```rust
let i; // 宣言
i = 1; // 初期化

let mut j; // 宣言(変更可)
j = 3;     // 初期化
j = 7;     // 変更
```

複数の変数を1行で初期化するには次のようにする。

```rust
let (t,u,v) = ("alpha","beta","charlie"); // t,u,vは定数
let (mut w, mut x) = ("delta","echo");    // w,xは定数ではない
let (y,z): (&str,&str) = ("foxtrot","golf")// 型指定 (thanks to @JunSuzukiJapan)
```

C++にはない機能として、Rustでは変数の宣言を上書きできる。
上書きするには現在の型と異なる型で宣言しなおす。

```rust
let a: i64 = 1;
println!("{}",a); // => "1"

let a: f64 = 3.14;
println!("{}",a); // => "3.14"
```

[TRPLの"Guessing game"](https://doc.rust-lang.org/1.30.0/book/first-edition/guessing-game.html)に使用例がある。

特殊な変数として、割り当てを無視するための`_`がある。

```rust
let _ = 1; // 割り当てを捨てる
let _ = test(); // 関数の戻り値を捨てる
```

これは主に後述の*destructuring let*、マッチやパターンと一緒に使う。
また、戻り値をかならず使うよう指定されている(`must_use`)関数の戻り値を捨てるために使われるらしい。

## 変数の属性(`const`と`static`)
Rustにも`const`と`static`が存在する。

`const`はC++11以降の`constexpr`のようなもの。
コンパイル時定数として扱われ、インライン化されるためメモリ上のアドレスは不定。

`static`は概ねC++のものと一緒。
起動時に1度だけ初期化され、ずっと同じアドレスにいる。

これら2つは宣言時に型を指定する必要がある。
また、これらはグローバルスコープに置くことができる。
ただし、これらは宣言の上書きや宣言と初期化の分離ができない。

命名に関して、`const`,`static`な変数には大文字の変数名を使用するという暗黙の了解があるようだ。

```rust
/* グローバルスコープ */
const C: i64 = 1;   // 定数
static S1: i64 = 2; // 定数
static mut S2: i64 = 3; // 変更可
```

## 型へのこだわり
Rustは型にかなり厳しい。
暗黙変換は基本的に存在しない。

```rust
let i: i64 = 3.5;     // エラー:宣言と初期化の型が合わない
println!("{}",3/4.); // エラー:割り算のオペランドの型が一致しない

let j = 1;
let k: f64 = j; // エラー:宣言と初期化の型が合わない
```

もちろんキャストはある(["*one of the most dangerous features of Rust!*"](https://doc.rust-lang.org/1.30.0/book/first-edition/casting-between-types.html))。
ただし、`as`は`static_cast`相当のキャストにしか使えず、Cライクな「何でもキャスト」をするには別の方法が必要。

```rust
let l = 1;
let m: f64 = j as f64; // j(整数)をf64にキャスト
```

## 関数
戻り値の型を指定しない場合はユニット型(空のタプル`()`)が戻り値になる。
それ以外のものを返したいときは型指定が必要。戻り値の型推論はない。
また、引数には型指定が必要。

`i32`同士を足し算する関数を書いてみる。

```rust
fn add(x: i32, y: i32) -> i32 {
    x + y
}
```

セミコロン無しの表現が`return`の役目を果たす。
もちろんC++スタイルで`return`を書くこともできる。

関数内関数を書くこともできる。
また、C++のラムダ式にあたる**クロージャ**もある。

## 関数ポインタ
先の`fn add(x: i32, y: i32) -> i32`の関数ポインタは

```rust
let x: fn(i32,i32) -> i32 = add;
```

と書ける。

## 配列
境界チェックがあり、領域外を参照すると異常終了。
アクセスの仕方はC++と同じで、添字は0オリジン。
アクセス時の添字は`usize`型でなければならない。

```rust
let a = [1,2,3,4,5]; // 5要素の配列
let b = [3;5];       // 5要素の配列、全要素を3で初期化
let c: [i32;10];      // 10要素の配列、要素の型はi32
```

配列は後述のスライスに暗黙変換できるので、配列自体は大した機能を持っていない。

## スライス
配列の一部分に対する参照。
C++の`valarray`にあった気がする。

```rust
let a = [1,2,3,4,5]; // 配列
let whole = &a[..];  // 配列全体への参照
let part = &a[1..4];  // 第1~3要素への参照
```

スライス`a`のメソッドのうち、便利そうなものを挙げておく。

|メソッド名      |機能                                  |
|:--------------|:------------------------------------|
|`a.contains(x)`|`a`に`x`が含まれているかを返す|
|`a.iter()`     |`a`のイテレータ(C++の`const_iterator`に相当)を返す。|
|`a.iter_mut()` |`a`の変更可能なイテレータ(C++の`iterator`に相当)を返す。|
|`a.len()`      |`a`の要素数を返す|
|`a.reverse()`  |`a`の要素の順番を逆転させる|
|`a.swap(x,y)`  |`a`の`x`番目と`y`番目の要素を交換する|
|`a.sort()`     |`a`をソート。(安定、$O(n\log n)$)|

## タプル
C++と違い、Rustでは組み込み型。
要素数とすべての要素の型が同じなら代入もできる。

```rust
let a = (1,2); // (i32,i32)のタプル
let b = (4.0,) // (f64)のタプル 
```
要素が1個のタプルを作るときは、最後の要素の後ろにカンマが必要。

タプルの中身を取り出すには2つの方法がある。
### *destructuring let*
`let`文を使って新しい変数にタプルの中身を割り当てることができる。
当然左辺と右辺で要素数が違ったりするとエラー。

```rust
let t1 = (1,2);
let t2 = (3,4);
let (x,y) = t1; // x=1, y=2となる
let (_,z) = t2; // z=4となる (_で要素を無視できる)
```

### 添え字でアクセス
添え字で要素を指定できる。添え字は0スタート。

```rust
let t = (10,20,30);
let a = t.0 // a=10
let b = t.1 // b=20
let c = t.3 // コンパイルエラー
```

添え字に変数は使用できない。out-of-boundsはコンパイル時にエラーとなる。

## if

条件式を囲うカッコがいらない。
([TRPL](https://doc.rust-lang.org/1.30.0/book/first-edition/if.html)から引用)

```rust
let x = 5;

if x == 5 {
    println!("x is five!");
}
```

C++のifは文(statement)だが、**Rustのifは式(expression)**である。(thanks to @moriturus)
式は値を返すので、三項演算子的な使い方もできる。
([TRPL](https://doc.rust-lang.org/1.30.0/book/first-edition/if.html)から引用)

```rust
let x = 5;

let y = if x == 5 { 10 } else { 15 }; // y = 10 で初期化
```

## ループ
Rustには無限ループ専用の構文がある。最適化のしやすさを狙ってのことらしい。

```rust
loop{
    println!("infinity!"); // 無限の infinity!
}
```

while文もある。

```rust
let mut i = 5;

while i < 5 {
    println!("loop!");
    i -= 1;
}
```

for文は、range-based forのような現代的な感じ。

```rust
let a = [0,1,2,3,4];
for v in a.iter() {   // 配列はイテレータに変換して使う
    println!("{}",v); // 0~4を順番に出力
}
```

数字を使いたいならこのように。

```rust
for i in 0..5 {
    println!("{}",i); // 0~4を順番に出力
}
```

`break`,`continue`はC++の用法に加え、ラベルと併用して多重ループを上手に扱える。

([TRPL](https://doc.rust-lang.org/1.30.0/book/first-edition/loops.html)から引用)

```rust
'outer: for x in 0..10 {
    'inner: for y in 0..10 {
        if x % 2 == 0 { continue 'outer; } // continues the loop over x
        if y % 2 == 0 { continue 'inner; } // continues the loop over y
        println!("x: {}, y: {}", x, y);
    }
}
```

([RBE](http://rustbyexample.com/flow_control/loop/nested.html)から引用)

```rust
'outer: loop {
    println!("Entered the outer loop");

    'inner: loop {
        println!("Entered the inner loop");

        // This would break only the inner loop
        //break;

        // This breaks the outer loop
        break 'outer;
    }

    println!("This point will never be reached");
}

println!("Exited the outer loop");
```

## Vec
C++で言う`vector`。
組み込み型でも何でもないが、便利だからかTRPLでは他の言語機能と並んで紹介されている。
配列と同様に境界チェックあり。

```rust
let v1: Vec<u64> = vec![]; // 空のVec生成
let v2 = vec![0;10];       // 10個の 0 を要素として生成
let v3 = vec![1,2,3,4,5];  // 要素リストから生成

for v in v3 { //for文で全要素を巡回
    println!("{}",v); // 1~5を順に表示
}
```

## 所有権
よくわからないので、[TRPL](https://doc.rust-lang.org/1.30.0/book/first-edition/ownership.html)を参考にする。

```rust
let v = vec![1, 2, 3];
let v2 = v;
println!("v[0] is: {}", v[0]); // エラー: v はムーブ済み
```

Rustでは、基本的に変数の移動は(コピーでなく)ムーブとして扱われるらしい。
これは、「一つのリソースの**所有権**はただ一つの変数に束縛される」という原則によるものとのこと。

ただし、同じことを`u64`型で行っても、暗黙的にコピーされるので問題は起きない。

```rust
let x: u64 = 32;
let x2 = x;
println!("x is: {}", x); // 問題なし
```

暗黙のコピーが起こるようにするには、`Copy`というTraitが必要らしい。
プリミティブ型は基本的に[^1]`Copy`を持っている。
Traitについては後述。

## (不変な)参照と借用
上で述べたように、Rustではムーブが基本。

```rust
fn print_all(v: Vec<u64>){
    for val in v {
        println!("{}",val);
    }
}

fn main(){
    let v = vec![1,2,3,4,5];
    print_all(v); // 問題なし
    print_all(v); // エラー: v はムーブ済み
}
```

引数として渡すときも、ムーブで渡されてしまう。

```rust
let v = vec![1,2,3,4,5];
for val in v { // 問題なし
    println!("{}",val);
}

for val in v { // エラー:vはムーブ済み
    println!("{}",val);
}
```
for文に渡してもムーブされる。

無論、このシチュエーションを切り抜けるための策はある。
Rustでは(不変な)参照はいくつ作っても良いことになっているので、それを使う。
(厳密には、`&T`が`Copy`を持つので引数として渡されるときにコピーされている、つまり「参照をコピーして渡す」ということらしい)

```rust
fn print_all(v: &Vec<u64>){
    for val in v {
        println!("{}",val);
    }
}

fn main(){
    let v = vec![1,2,3,4,5];
    print_all(&v); // 問題なし
    print_all(&v); // 問題なし
}
```

```rust
let v = vec![1,2,3,4,5];
for val in &v { // 問題なし
    println!("{}",val);
}

for val in &v { // 問題なし
    println!("{}",val);
}
```

Rustでは、このように参照を通じて所有権を**借用(borrow)**することができる。

## 変更可能な参照
不変な参照だけでは世の中を渡り歩けない。
そこで、変更可能な参照`&mut`を使う。
変更可能な参照を通じて変数にアクセスするには、`*`が必要。

([TRPL](https://doc.rust-lang.org/1.30.0/book/first-edition/references-and-borrowing.html#mut-references)から引用)

```rust
let mut x = 5;
{
    let y = &mut x;
    *y += 1;
}
println!("{}", x);
```

変更可能な参照は一時的に所有権を移動するのと同義である。
したがって、一度に一つしか存在できない。
(ムーブはできるがコピーはできない)
また参照が存在する間は元の変数は使用できない。

上の例では、参照のスコープを抜けてから`println`を使用している。
スコープを表す波括弧を取り除くと、エラーが起こる。

## 生存期間(lifetime)
(日本語名は拙訳)
よくわからないので、[TRPL](https://doc.rust-lang.org/1.30.0/book/first-edition/lifetimes.html)を参考にする。

次のようなコードを考える。

```rust
let r;
{
    let i = 1;
    r = &i;
}
println!("{}", r);
```

`r`に束縛された参照が`println`で使われる時には、すでに元の変数のスコープを抜けているので何が起こるかわからない。
(C++で同じようなコードを書くと未定義?)

Rustではこのコードはコンパイルを通らない。
これだけなら、「コンパイル時にスコープチェックができるようになった」だけである。

ここからが、TRPLをして「*Rustの最も独特かつ尊重すべき機能であり、Rustを利用する開発者が熟知すべきもの*」と言わしめるところである。

次のコードを見てみよう。

```rust
fn skip_prefix(line: &str, prefix: &str) -> &str {
    // ...
}

let line = "lang:en=Hello World!";
let lang = "en";

let v;
{
    let p = format!("lang:{}=", lang);
    v = skip_prefix(line, p.as_str());
}
println!("{}", v);
```

このコードは次のようなエラーでコンパイルを通らない。

```
error[E0106]: missing lifetime specifier
 --> test.rs:1:45
  |
1 | fn skip_prefix(line: &str, prefix: &str) -> &str {
  |                                             ^ expected lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `line` or `prefix`
```

参照を返す際には"lifetime parameter"なるものが必要らしい。

`skip_prefix`を直すと次のようになる。

```rust
fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str {
    // ...
}
```

`'a`,`'b`が"lifetime parameter"(**生存期間パラメータ**)である。
`'a`が`line`の、`'b`が`prefix`の生存期間を表す。

返値の`&'a str`は、「生存期間を`line`と同じにする」という設定になったのである。
`line`は`main`関数内では生きつづけるので、返値もおなじ生存期間になったことで`println!`で問題なく使用できる。

特殊な生存期間パラメータとして、`'static`がある。
名前の通り、プログラム開始から終了まで生き続ける。

ちなみに、すべての参照引数に生存期間パラメータが必要なわけではないので、上の関数は次のようにも書ける。

```rust
fn skip_prefix<'a>(line: &'a str, prefix: &str) -> &'a str {
    // ...
}
```

(`'b`は関数内で使用されていないので省略できる)

## 構造体
C++とだいたい一緒。
メンバ宣言は、`<メンバ名>:<型>`の形。

```rust
struct Foo{
    m1: u64,
    m2: f32,
}
```

C++と違い、`const`、`static`メンバは作れない。
(`const`メンバについては標準ライブラリに抜け穴が用意されているようだが)

また、メンバレベルでのアクセス制御をするには、モジュールを切り分ける必要がある。

参照をメンバとして取ることもできるが、その際には生存期間の指定が必要になる。
(「*構造体が参照よりも長生きしないようにするため*」らしい)

```rust
struct Foo<'a>{
   m: &'a i32,
}
```

##構造体の初期化

```rust
struct Foo{
    m1: i32,
    m2: i32,
    m3: i32,
}
```

を初期化するには、次のようにする。

```rust
let f = Foo{m1: 1, m2: 3, m3: 5};
```

構文としては、`<構造体名> { <メンバ名> : <メンバの値>, ... }`となる。
このとき、メンバの順番はどうでもよいが、必ずすべてのメンバを初期化しなければならない。

また、既存の構造体インスタンスの値を一部だけ変更してコピーすることもできる。

```rust
let f1 = Foo{m1: 1, m2: 3, m3: 5};
let f2 = Foo{m1: 0, m3: 7, .. f1}; // m1: 0, m2: 3, m3: 7
```

## タプル構造体
Rustではタプルに名前をつけて新たな型を作ることができる。

```rust
struct A(u64);
struct B(u64);

let a = A(1);
let b = B(2);
// b = a は不可能(AとBは違う型)
```

要素にアクセスするときは、普通のタプル同様に添え字アクセスができる。
また、*destructuring let*もすこし書き方が違うが可能である。

```rust
struct Test(u64,u64,u64);

let t = Test(1,2,3);
let Test(_,i,j) = t; // i=2, j=3
```

## 空の構造体 (Unit-like struct)
Rustでも要素のない構造体を作ることができる。

```rust
struct Empty1{}  //要素のない通常の構造体
struct Empty2;   //要素のない構造体(特別な記法)
struct Empty3(); //要素のないタプル構造体

/* 生成方法 */
let e1 = Empty1{};
let e2 = Empty2;
let e3 = Empty3();
```

## 列挙型(enum)
C++のenumとは違って、整数型以外の型も扱える。
もっと言えば、各要素が異なる型であっても良い。
いわゆるタグ付き共用体のようなもの。

```rust
enum Test{
  A,       // 空の構造体
  B(i32),  // (i32)のタプル
  C{x: f64} // 構造体
}

let x = Test::A;
let y = Test::B(16);
let z = Test::C{x: 3.14};
```

## 構造体などのメソッドの実装
構造体`Foo`を次のように定義する。

```rust
struct Foo{
    m: i32
}
```

構造体`Foo`にメソッドを実装するには、`impl`ブロックを使う。
C++の`const`や`static`にあたるメソッドも実装できる。

```rust
impl Foo{
    fn answer() -> i32 { // staticメソッド
        42
    }

    fn get_m(&self) -> i32 { // constメソッド
        self.m
    }

    fn set_m(&mut self, m_new: i32){ // メンバを変更するメソッド
        self.m = m_new;
    }
}
```

C++との違いとして、staticでないメソッドは引数で`self`(あるいはその参照)を取る必要がある。
`self`も引数でしか無いので、メンバを利用する際には`self.`でプレフィックスする必要があるし、`self`を参照で取らないとムーブされてしまいややこしいことになる。
(「このメソッドを使うならこの構造体の役目は終わり」ということであえてムーブしてしまうこともあるようだが)

生存期間付きの構造体のメソッドを定義するときは、`impl`ブロックにも生存期間を書かないといけない。

```rust
impl<'a> Foo<'a>{
    // ...
}
```

なお、タプル構造体や列挙型についても同様にメソッドを定義できる。

## マッチ
### マッチの基本
`match`はC++の`switch`のようなもの。

([TRPL](https://doc.rust-lang.org/1.30.0/book/first-edition/patterns.html)から引用)

```rust
let x = 1;

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

また、`enum`にマッチすることもできる。
(ついでに便利な書き方も紹介)

```rust
enum Test {
    A,
    B,
    C,
    D,
};

let x = Test::A;

match x {
    Test::A => println!("A"),
    Test::B => println!("B"),
    Test::C | Test::D => println!("C or D"); // 複数の状況にマッチできる
    _ => {}, // 何もしない
}
```

`_`はC++で言う`default`の役割を果たしている。
(根底にはもう少しややこしい仕組みがある、後述)

Rustの`match`は、対象となる変数が(型として)取りうる値全てについて処理を書かないといけない。
特定の値についてのみ処理を書きたいなら、残りは`_`で処理すれば良い。

### マッチは「式」
ifが式であったように、matchも式なので値を返すことができる。
[ifの節](#if)で書いた式と同じものをmatchで書いてみる。

```rust
let x = 5;

let y = match x {
    5 => 10,
    _ => 15
} // y = 10 で初期化
```

この例だとif式で書いた方がましだが、後々enumとの組み合わせ等で本領が発揮される。

### `Destructuring`

`match`式の中でも`destructuring let`のようにstructやtupleの中身を取り出すことができる。

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

let origin = Point { x: 0, y: 0 };

match origin {
    Point { x, y } => println!("({},{})", x, y),
}
```


### ガード

# まだ記事に書いてないC++との違い

- 関数オーバーロードがない(演算子オーバーロードはできる)
- デフォルト引数がない
- 構造体同士の継承はできない(Trait同士の継承はできる)
- `constexpr`関数が弱い

# まだまだあるけど
続きは随時追記していきます


# 最後に
Rustユーザーの方のツッコミお待ちしております。

[^1]: 配列、スライスは`Copy`を持たず、タプルは全要素が`Copy`を持つ型であるときのみタプル自身が`Copy`を持つ