Rustの基本文法（変数と可変性/データ型）

# 基本文法（変数と可変性/データ型）

公式サイトを参考にして、基本文法（変数と可変性/データ型）の手順をまとめている。

https://doc.rust-jp.rs/book-ja/ch03-00-common-programming-concepts.html

## 変数と可変性

### 変数について

変数は標準で**不変**になる。

公式ドキュメントでは、下記が記載されている。

> 第2章で触れた通り、変数は標準で不変になります。
これは、 Rustが提供する安全性や簡便な並行性の利点を享受する形でコードを書くための選択の1つです。
> 

変数が不変であることを確認する。

新しくプロジェクトを作成する

```bash
vscode ➜ /workspaces/rust_devcontainer (master) $ cargo new variable
     Created binary (application) `variable` package
vscode ➜ /workspaces/rust_devcontainer (master) $ 
vscode ➜ /workspaces/rust_devcontainer (master) $
```

サンプルコード）

```rust
fn main() {
    let x = 5;
    println!("The value of x is: {}", x);     // xの値は{}です
    x = 6;
    println!("The value of x is: {}", x);
}
```

実行結果）エラー「不変変数xに2回代入できない」が表示される。

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         -
  |         |
  |         first assignment to `x`
  |         help: consider making this binding mutable: `mut x`
3 |     println!("The value of x is: {}", x);     // xの値は{}です
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable

For more information about this error, try `rustc --explain E0384`.
error: could not compile `variable` (bin "variable") due to previous error
```

場合によっては、変数を可変にしたいこともあると思われる。
その場合は、変数名の前に `mut` キーワードを付けることで可変にできる。

サンプルコード）

```rust
fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);     // xの値は{}です
    x = 6;
    println!("The value of x is: {}", x);
}
```

実行結果）xの値「5」と代入後のxの値「6」が表示される。

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
The value of x is: 5
The value of x is: 6
```

### 変数と定数の違い

定数を使用する場合は、`let`キーワードの代わりに、`const`キーワードを宣言する必要がある。
また、定数は不変のため`mut`キーワードを使用することができない。

定数は、どんな範囲でも定義できる。公式には下記が記載されている。

> 定数はどんなスコープでも定義できます。グローバルスコープも含めてです。
なので、 いろんなところで使用される可能性のある値を定義するのに役に立ちます。
> 

サンプルコード）

```rust
const MAX_POINTS: u32 = 100_000;

fn main() {
    const X_VALUE: i32 = 5;
    println!("The value of X_VALUE is: {}", X_VALUE);     // xの値は{}です
    println!("The value of MAX_POINTS is: {}", MAX_POINTS);
}
```

実行結果）X_VALUEの値「5」とMAX_POINTSの値「100000」が表示される。

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
The value of X_VALUE is: 5
The value of MAX_POINTS is: 100000
```

### シャードイング

前に定義した変数と同じ変数名を宣言することができる。
前と同じ変数名で定義された場合、新しく定義された変数は、前の変数を覆い隠してしまう。

公式には下記が記載されている。

> Rustaceanはこれを最初の変数は、 2番目の変数に***覆い隠さ***れたと言い、この変数を使用した際に、2番目の変数の値が現れるということです。 以下のようにして、同じ変数名を用いて変数を覆い隠し、`let`キーワードの使用を繰り返します:
> 

サンプルコード）

```rust
fn main() {
    let x = 5;

    let x = x + 1;

    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {}", x);
    }

    println!("The value of x is: {}", x);
}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
The value of x in the inner scope is: 12
The value of x is: 6
```

公式は下記の解説をしている。

> このプログラムはまず、`x`を`5`という値に束縛します。それから`let x =`を繰り返すことで`x`を覆い隠し、 元の値に`1`を加えることになるので、`x`の値は`6`になります。 3番目の`let`文も`x`を覆い隠し、以前の値に`2`をかけることになるので、`x`の最終的な値は`12`になります。 括弧を抜けるとシャドーイングは終了し、`x`の値は元の`6`に戻ります。 このプログラムを走らせたら、以下のように出力するでしょう。
> 

重要なメリットとしては、値をかえつつ、同じ変数名を使いまわせるところになる。

<aside>
💡 注意する点としては、変数を`mut`するのとは違うため、変数の型を可変にすることは許されていない。

</aside>

サンプルコード）

```rust
fn main() {
    let spaces = "   ";
    let spaces = spaces.len();
    let spaces = spaces + 1;
    println!("The value of spaces : {}", spaces);

    let mut mut_spaces = "   ";
    mut_spaces = mut_spaces.len();
    let mut_spaces = mut_spaces + 1;
    println!("The value of mut_spaces : {}", mut_spaces);
}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
error[E0308]: mismatched types
 --> src/main.rs:8:18
  |
7 |     let mut mut_spaces = "   ";
  |                          ----- expected due to this value
8 |     mut_spaces = mut_spaces.len();
  |                  ^^^^^^^^^^^^^^^^ expected `&str`, found `usize`
  |
help: try removing the method call
  |
8 -     mut_spaces = mut_spaces.len();
8 +     mut_spaces = mut_spaces;
  |

error[E0369]: cannot add `{integer}` to `&str`
 --> src/main.rs:9:33
  |
9 |     let mut_spaces = mut_spaces + 1;
  |                      ---------- ^ - {integer}
  |                      |
  |                      &str

Some errors have detailed explanations: E0308, E0369.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `variable` (bin "variable") due to 2 previous errors
vscode ➜ /workspaces/rust_devcontainer/variable (master)
```

## データ型

Rustは、静的型付き言語になるため、コンパイル時に変数の型が判明されている必要があります。

### スカラー型

単独の値を表す。
Rustには、4つのスカラー型がある。

- 整数型
- 浮動小数点数
- 論理値
- 文字

**整数型**

整数とは、小数点のない数値のことになる。

符号付きか符号なしかを選ぶことができ、明示的なサイズを指定できる。

| ビットの大きさ | 符号付き(+-) | 符号なし |
| --- | --- | --- |
| 8bit | i8 | u8 |
| 16bit | i16 | u16 |
| 32bit | i32 | u32 |
| 64bit | i64 | u64 |
| architecture size | isize | usize |

サンプルコード)

```rust
fn main() {
    // 符号付き
    let bit_8:i8 = 8;
    let bit_16:i16 = 16;
    let bit_32:i32 = 32;
    let bit_64:i64 = 64;
    let bit_arch:isize = -64;
    println!("The value of bit_8 : {}", bit_8);
    println!("The value of bit_16 : {}", bit_16);
    println!("The value of bit_32 : {}", bit_32);
    println!("The value of bit_64 : {}", bit_64);
    println!("The value of bit_arch : {}", bit_arch);
    println!("====================================");
    // 符号なし
    let ubit_8:u8 = 8;
    let ubit_16:u16 = 16;
    println!("The value of ubit_8 : {}", ubit_8);
    println!("The value of ubit_16 : {}", ubit_16);

}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/variable`
The value of bit_8 : 8
The value of bit_16 : 16
The value of bit_32 : 32
The value of bit_64 : 64
The value of bit_arch : -64
====================================
The value of ubit_8 : 8
The value of ubit_16 : 16
```

**整数リテラル**

整数リテラルは型を後ろに明示することができる。

| 整数リテラル | 補足 |
| --- | --- |
| 15i8 | i8型の10進数 |
| 11u16 | u16型の8進数 |
| 11i32 | i32型の16進数 |
| 11u64 | u64型の2進数 |
| 123_456 | 数値の間にアンダーバーを入れられる |
| 15_i8 | 型の間にアンダーバーを入れられる |
| 0x_A | プレフィックスの間にアンダーバーを入れられる
例）16進数 |

サンプルコード）

```rust
fn main() {
    let bit_8 = 15i8;
    let bit_16 = 11u16;
    let bit_32 = 11i32;
    let bit_ = 123_456;
    let bit_8_ = 15_i8;
    let bit_prefix = 0x_A;
    println!("The value of bit_8 : {}", bit_8);
    println!("The value of bit_16 : {}", bit_16);
    println!("The value of bit_32 : {}", bit_32);
    println!("The value of bit_ : {}", bit_);
    println!("The value of bit_8_ : {}", bit_8_);
    println!("The value of bit_prefix : {}", bit_prefix);

}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
The value of bit_8 : 15
The value of bit_16 : 11
The value of bit_32 : 11
The value of bit_ : 123456
The value of bit_8_ : 15
The value of bit_prefix : 10
```

**浮動小数点数**

Rustの浮動小数点には、2種類の基本型がある。

| ビットの大きさ | 浮動小数点数 |
| --- | --- |
| 32bit | f32 |
| 64bit | f64 |

※基準型は`f64`になる。

サンプルコード）

```rust
fn main() {
    let x = 2.2; // f64
    let y: f32 = 3.2; // f32
    println!("The value of x : {}", x);
    println!("The value of y : {}", y);
}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
The value of x : 2.2
The value of y : 3.2
```

**数値演算**

Rustには、標準的な数学演算が用意されています。

- 足し算
- 引き算
- 掛け算
- 割り算
- 余り

サンプルコード）

```rust
fn main() {
    // addition
    // 足し算
    let sum = 5 + 10;
    println!("{}",sum);

    // subtraction
    // 引き算
    let difference = 95.5 - 4.3;
    println!("{}",difference);

    // multiplication
    // 掛け算
    let product = 4 * 30;
    println!("{}",product);

    // division
    // 割り算
    let quotient = 56.7 / 32.2;
    let floored = 2 / 3; // Results in 0
                         // 結果は0
    println!("{}",quotient);
    println!("{}",floored);

    // remainder
    // 余り
    let remainder = 43 % 5;
    println!("{}",remainder);
}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/variable`
15
91.2
120
1.7608695652173911
0
3
```

**論理値型**

true/falseにて論理型の値を定義できる。
論理型は、`bool`と指定できる。

サンプルコード）

```rust
fn main() {
    let t = true;
    let f: bool = false;

		// if文で判定
    if t {
        println!("true");
    }
		
    if f {
        println!("true");
    }else {
        println!("false");
    }
}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/variable`
true
false
```

**文字型**

Rustには、文字列も定義できます。
Rustの文字列は、char型・str型・String型を指定することができる。

サンプルコード）

```rust
fn main() {
    // str型にて定義
    let string = "Hello, World";

    println!("{}",string);

}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
Hello, World
```

char型・str型・String型の内容は、下記の記事にて簡潔にまとめられている。

参考URL：[https://zenn.dev/moreyhat/articles/1d85c62e93ae86](https://zenn.dev/moreyhat/articles/1d85c62e93ae86)

### 複合型

複数の値を一つの値をまとめたものが複合型になる。
複合型には、２つの基本的なものがある。

- タプル
- 配列

**タプル**

丸かっこ（）の中に複数の型の値をカンマ区切りで入れることができる。
特定の値を取り出すときは、タプルのあとにドットをつけインデックス番号を指定する。

サンプルコード）

```rust
fn main() {
    let tup: (i32, f64, u8) = (-500, 6.4, 1);
		println!("{}, {}, {}", tup.0, tup.1 ,tup.2);
}
```

実行結果)

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
-500, 6.4, 1
```

タプルから個々の値を取り出して出力することができる。

サンプルコード）

```rust
fn main() {
    let tup = (500, 6.4, 1);

    let (_x, _y, _z) = tup;

    println!("The value of _x is: {}", _x);
}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
The value of _x is: 500
```

**配列**

*配列*によっても、複数の値のコレクションを得ることができる。
タプルと異なり、配列の要素は**同じ型の値**でないといけない。
特定の値を指定する場合は角カッコ[ ]の中にインデックス番号を指定する。

<aside>
💡 Rustの配列は、 **固定長**なため一度宣言されたら、**サイズを伸ばすことも縮めることもできない**。

</aside>

サンプルコード）

```rust
fn main() {
    let a = [1, 2, 3, 4, 5];
    println!("a[0]の値は、{}", a[0]);

}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
a[0]の値は、1
```

配列に、要素の型と要素数を定義することもできる。
サンプルコード）符号あり32bitの数値を5つ定義しているコード。`[i32; 5]`

```rust
fn main() {
    let a: [i32; 5] = [1, 2, 3, 4, 5];
    let first = a[0];
    let five= a[4];
		println!("first の値は、{}", first );
		println!("fiveの値は、{}", five);
}
```

実行結果）

```bash
vscode ➜ /workspaces/rust_devcontainer/variable (master) $ cargo run
   Compiling variable v0.1.0 (/workspaces/rust_devcontainer/variable)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/variable`
first の値は、1
fiveの値は、5
```

以上が基本文法（変数と可変性/データ型）になる。