Rust By Exampleを勉強した記録: 3

Rust By Exampleの記録、3つ目です




# Variable Bindings

https://doc.rust-lang.org/rust-by-example/variable_bindings.html


## ソースコード

<details><summary>ソースコード</summary>

```rust
fn main() {
    let an_integer = 1u32;
    let a_boolean = true;
    let unit = ();

    let copied_integer = an_integer;

    println!("An integer: {:?}", copied_integer);
    println!("A boolean: {:?}", a_boolean);
    println!("Meet the unit value: {:?}", unit);

    let _unused_variable = 3u32;

    let _noisy_unsed_variable = 2u32;
}
```
</details>

## 出力結果
```
An integer: 1
A boolean: true
Meet the unit value: ()
```

## Try

`_`を変数名につけることで、明示的に未使用変数をサイレント化できます
つけていない場合、未使用変数がある場合は、はっきりとコンパイラが未使用変数を指摘してくれます

```diff
-    let noisy_unsed_variable = 2u32;
+    let _noisy_unsed_variable = 2u32;
```

```
warning: unused variable: `noisy_unsed_variable`
  --> src/main.rs:14:9
   |
14 |     let noisy_unsed_variable = 2u32;
   |         ^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_noisy_unsed_variable`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: `variable_bindings` (bin "variable_bindings") generated 1 warning
```

# Mutability

https://doc.rust-lang.org/rust-by-example/variable_bindings/mut.html

## ソースコード

<details><summary>ソースコード</summary>

```rust
fn main() {
    let _immutable_binding = 1;
    let mut mutable_binding = 1;

    println!("Before mutation: {}", mutable_binding);

    mutable_binding += 1;

    println!("After mutation: {}", mutable_binding);

    //_immutable_binding += 1;
}
```
</details>

## 出力結果
```
Before mutation: 1
After mutation: 2
```

# Scope and Shadowing

https://doc.rust-lang.org/rust-by-example/variable_bindings/scope.html

## ソースコード

<details><summary>ソースコード</summary>

```rust
fn main() {
    // Scope
    let long_lived_binding = 1;

    {
        let short_lived_binding = 2;

        println!("inner short: {}", short_lived_binding);
    }

    //println!("outer short: {}", short_lived_binding);

    println!("outer long: {}", long_lived_binding);

    // Shadowing
    let shadowd_binding = 1;

    {
        println!("before being shadowd: {}", shadowd_binding);

        let shadowd_binding = "abc";

        println!("shadowd in inner block: {}", shadowd_binding);
    }
    println!("outside inner block: {}", shadowd_binding);

    let shadowd_binding = 2;
    println!("shadowd in outer block: {}", shadowd_binding);
}
```
</details>

## 出力結果
```
inner short: 2
outer long: 1
before being shadowd: 1
shadowd in inner block: abc
outside inner block: 1
shadowd in outer block: 2
```

## Try
```diff
-    //println!("outer short: {}", short_lived_binding);
+    println!("outer short: {}", short_lived_binding);
```

スコープ外の変数を使おうとすると、エラーとなります

```
error[E0425]: cannot find value `short_lived_binding` in this scope
  --> src/main.rs:10:33
   |
10 |     println!("outer short: {}", short_lived_binding);
   |                                 ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `long_lived_binding`

For more information about this error, try `rustc --explain E0425`.
```


# Declare first

https://doc.rust-lang.org/rust-by-example/variable_bindings/declare.html

## ソースコード

<details><summary>ソースコード</summary>

```rust
fn main() {
    let a_binding;

    {
        let x = 2;

        a_binding = x * x;
    }

    println!("a binding: {}", a_binding);

    let another_binding;

    //println!("another binding: {}", another_binding);

    another_binding = 1;

    println!("another binding: {}", another_binding);
}
```
</details>

## 出力結果
```
a binding: 4
another binding:
```

## Try
```diff
-    //println!("another binding: {}", another_binding);
+    println!("another binding: {}", another_binding);
```

```
error[E0381]: used binding `another_binding` is possibly-uninitialized
  --> src/main.rs:14:37
   |
12 |     let another_binding;
   |         --------------- binding declared here but left uninitialized
13 |
14 |     println!("another binding: {}", another_binding);
   |                                     ^^^^^^^^^^^^^^^ `another_binding` used here but it is possibly-uninitialized
   |
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0381`.
```


# Freezing

https://doc.rust-lang.org/rust-by-example/variable_bindings/freeze.html

## ソースコード

<details><summary>ソースコード</summary>

```rust
fn main() {
    let mut _mutable_integer = 7i32;

    {
        let _mutable_integer = mutable_integer;

        //_mutable_integer = 50;
    }

    _mutable_integer = 3;
}
```
</details>

## 出力結果
```
mutable integer: 3
```

## Try
```diff
-        //_mutable_integer = 50;
+        _mutable_integer = 50;
```

shadowingはmutable、imutableに関係なく実行できる
元がmutableな変数であっても、imutableな変数でshadowingすると、変数はimutableとなり、値がfreezingする

```
error[E0425]: cannot find value `mutable_integer` in this scope
 --> src/main.rs:5:32
  |
5 |         let _mutable_integer = mutable_integer;
  |                                ^^^^^^^^^^^^^^^
  |
help: a local variable with a similar name exists, consider renaming `_mutable_integer` into `mutable_integer`     
  |
2 |     let mut mutable_integer = 7i32;
  |             ~~~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0425`.
```

# Casting

https://doc.rust-lang.org/rust-by-example/types/cast.html

<details><summary>ソースコード</summary>

```rust
fn main() {
    let decimal = 65.4321_f32;
    //let integer: u8 = decimal;
    let integer = decimal as u8;
    let character = integer as char;
    //let character = decimal as char;

    println!("Casting: {} -> {} -> {}", decimal, integer, character);

    println!("65534 as a u16 is: {}", 65534 as u16);
    println!("65535 as a u16 is: {}", 65535 as u16);
    //println!("65536 as a u16 is: {}", 65536 as u16);
 
    //println!("1000 as a u8 is : {}", 1000 as u8);

    println!("  -1 as a u8 is : {}", (-1i8) as u8);

    println!("1000 mod 256 is : {}", 1000 % 256);

    println!(" 128 as a i16 is: {}", 128 as i16);
    //println!(" 128 as a i8 is : {}", 128 as i8);

    //println!("-129 as a i8 is : {}", -129 as i8);
    println!("-128 as a i8 is : {}", -128 as i8);
    println!(" 127 as a i8 is : {}", 127 as i8);
    //println!(" 128 as a i8 is : {}", 128 as i8);

    println!(" 300.0 as u8 is : {}", 300.0_f32 as u8);
    println!("-100.0 as u8 is : {}", -100.0_f32 as u8);
    println!("   nan as u8 is : {}", f32::NAN as u8);

    unsafe {
        // 300.0 as u8 is 44
        println!(" 300.0 as u8 is : {}", 300.0_f32.to_int_unchecked::<u8>());
        // -100.0 as u8 is 156
        println!("-100.0 as u8 is : {}", (-100.0_f32).to_int_unchecked::<u8>());
        // nan as u8 is 0
        println!("   nan as u8 is : {}", f32::NAN.to_int_unchecked::<u8>());
    }
}
```
</details>


## 65.332 -> 65 -> A

### ソースコード

```rust
    let decimal = 65.4321_f32;
    //let integer: u8 = decimal;
    let integer = decimal as u8;
    let character = integer as char;
    //let character = decimal as char;

    println!("Casting: {} -> {} -> {}", decimal, integer, character);
```

### 出力結果
```
Casting: 65.332 -> 65 -> A
```

### Try
```diff
- //let integer: u8 = decimal;
+ let integer: u8 = decimal;
```
暗黙的なキャストは許されていない
エラーメッセージがキャストを提案してこないところが上品だ
```
error[E0308]: mismatched types
 --> src/main.rs:6:23
  |
6 |     let integer: u8 = decimal;
  |                  --   ^^^^^^^ expected `u8`, found `f32`
  |                  |
  |                  expected due to this

For more information about this error, try `rustc --explain E0308`.
```

```diff
-    //let character = decimal as char;
+    let character = decimal as char;
```
`u8`でないと`char`にキャストできない
```
error[E0604]: only `u8` can be cast as `char`, not `f32`
 --> src/main.rs:9:21
  |
9 |     let character = decimal as char;
  |                     ^^^^^^^^^^^^^^^ invalid cast
  |
help: try `char::from_u32` instead (via a `u32`)
 --> src/main.rs:9:21
  |
9 |     let character = decimal as char;
  |                     ^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0604`.
```

## 1000 as a u16

u16は0から65,535（0b1111_1111_1111_1111）までを表現できる

### ソースコード
```rust
    println!("1000 as a u16 is: {}", 1000 as u16);
```
### 出力結果
```
1000 as a u16 is: 1000
```

### Try
```rust
    println!("65534 as a u16 is: {}", 65534 as u16);
    println!("65535 as a u16 is: {}", 65535 as u16);
    //println!("65536 as a u16 is: {}", 65536 as u16);
```

最大値より大きい値をキャストしようとすると、エラーとなる

```
error: literal out of range for `u16`
  --> src/main.rs:14:39
   |
14 |     println!("65536 as a u16 is: {}", 65536 as u16);
   |                                       ^^^^^
   |
   = note: the literal `65536` does not fit into the type `u16` whose range is `0..=65535`
   = note: `#[deny(overflowing_literals)]` on by default
```
```
65534 as a u16 is: 65534
65535 as a u16 is: 65535
```

## 1000 - 256 - 256 - 256 = 232

`u8`は0から255（0b1111_1111）までのため、1000は範囲外でエラー
ここら辺が例と結果が違うから、デフォルトの仕様が変わったのかな？

### ソースコード
```rust
    // 1000 - 256 - 256 - 256 = 232
    println!("1000 as a u8 is : {}", 1000 as u8);
```
```
error: literal out of range for `u8`
  --> src/main.rs:18:38
   |
18 |     println!("1000 as a u8 is : {}", 1000 as u8);
   |                                      ^^^^
   |
   = note: the literal `1000` does not fit into the type `u8` whose range is `0..=255`
   = note: `#[deny(overflowing_literals)]` on by default
```

### Try
```
1000(0b0011_1110_1000)
 232(0b0000_1110_1000)
```
>    // 1000 - 256 - 256 - 256 = 232
    // Under the hood, the first 8 least significant bits (LSB) are kept,
    // while the rest towards the most significant bit (MSB) get truncated.
:::note info
最下位8ビット（LSB）は保持され、残りの最上位8ビット（MSB）は切り捨てられる
:::
と、ありますが、今はエラーとなるようです
```
> rustc --version
rustc 1.79.0 (129f3b996 2024-06-10)
```

## -1 + 256 = 255

`-1（0b1111_1111）`をu8にキャストすると、`255（0b1111_1111）`となる

### ソースコード
```rust
    println!("  -1 as a u8 is : {}", (-1i8) as u8);
```

### 出力結果
```
  -1 as a u8 is : 255
```

## mod

```
1000 - 256 = 744
744 - 256 = 488
488 - 256 = 232
```

### ソースコード
```
    println!("1000 mod 256 is : {}", 1000 % 256);
```

### 出力結果
```
1000 mod 256 is : 232
```

## 128 as i16

### ソースコード
```
    println!(" 128 as a i16 is: {}", 128 as i16);
    //println!(" 128 as a i8 is : {}", 128 as i8);
```

### 出力結果
```
 128 as a i16 is: 128
```

### Try
```diff
-    //println!(" 128 as a i8 is : {}", 128 as i8);
+    println!(" 128 as a i8 is : {}", 128 as i8);
```

```
error: literal out of range for `i8`
  --> src/main.rs:28:38
   |
28 |     println!(" 128 as a i8 is : {}", 128 as i8);
   |                                      ^^^
   |
   = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
   = help: consider using the type `u8` instead
   = note: `#[deny(overflowing_literals)]` on by default
```

## -129 as a i8

`i8`は`-128（0b1000_0000）`から`127（0b0111_1111）`を表現できる

### ソースコード
```rust
    println!("-129 as a i8 is : {}", -129 as i8);
    println!("-128 as a i8 is : {}", -128 as i8);
    println!(" 127 as a i8 is : {}", 127 as i8);
    println!(" 128 as a i8 is : {}", 128 as i8);
```

```
error: literal out of range for `i8`
  --> src/main.rs:23:38
   |
23 |     println!("-129 as a i8 is : {}", -129 as i8);
   |                                      ^^^^
   |
   = note: the literal `-129` does not fit into the type `i8` whose range is `-128..=127`
   = help: consider using the type `i16` instead
   = note: `#[deny(overflowing_literals)]` on by default

error: literal out of range for `i8`
  --> src/main.rs:26:38
   |
26 |     println!(" 128 as a i8 is : {}", 128 as i8);
   |                                      ^^^
   |
   = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
   = help: consider using the type `u8` instead
```

## 300.0_f32 as u8
> Since Rust 1.45, the `as` keyword performs a *saturating cast* when casting from float to int. If the floating point value exceeds the upper bound or is less than the lower bound, the returned value will be equal to the bound crossed.

Google翻訳より

:::note info
Rust 1.45 以降、`as` キーワードは float から int にキャストするときに *飽和キャスト* を実行します。浮動小数点値が上限を超えるか下限より小さい場合、返される値は境界を越えた値と等しくなります。
:::

```
    println!(" 300.0 as u8 is : {}", 300.0_f32 as u8);
    println!("-100.0 as u8 is : {}", -100.0_f32 as u8);
    println!("   nan as u8 is : {}", f32::NAN as u8);
```

```
 300.0 as u8 is : 255
-100.0 as u8 is : 0
   nan as u8 is : 0
```

floatはまったくわからないので、飛ばす

## unsafe

```rust
    /* unsafe */ {
        // 300.0 as u8 is 44
        println!(" 300.0 as u8 is : {}", 300.0_f32.to_int_unchecked::<u8>());
        // -100.0 as u8 is 156
        println!("-100.0 as u8 is : {}", (-100.0_f32).to_int_unchecked::<u8>());
        // nan as u8 is 0
        println!("   nan as u8 is : {}", f32::NAN.to_int_unchecked::<u8>());
    }
```

オーバーフローを起こす可能性がある計算をチェックしないで実行しようとすると、`unsafe`がないから、エラーとなる

```
error[E0133]: call to unsafe function `core::f32::<impl f32>::to_int_unchecked` is unsafe and requires unsafe function or block
  --> src/main.rs:37:42
   |
37 |         println!(" 300.0 as u8 is : {}", 300.0_f32.to_int_unchecked::<u8>());
   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
   |
   = note: consult the function's documentation for information on how to avoid undefined behavior

(略)
```

# 後書き
後半はよくわかりませんでした
小数点表現は基本情報をとったときに勉強して以来なので、まじめに勉強したほうがいいかもしれません