第15回です。
前回はこちら。
[第15回の様子]
2021/10/20に第15回を開催した。
内容としてはRust By Example 日本語版の「4.4. 値のフリーズ」、「5. Types」、「5.1. 型キャスティング」に取り組んだ。
参加者はちょっと戻ってきて、全部で8人。
Slackでの書き込みは相変わらず少なめだが、dojo開催中の会話が少し増えてきてる気がする。
[学んだこと]
- 4.4. 値のフリーズ
- mutのついている変数もスコープを変えてmutなしでシャドウイングすると、フリーズされて変更不可となる
fn main() { let mut _mutable_integer = 7i32; { let _mutable_integer = _mutable_integer; _mutable_integer = 50; } } // コンパイルエラー Compiling playground v0.0.1 (/playground) error[E0384]: cannot assign twice to immutable variable `_mutable_integer` --> src/main.rs:10:9 | 6 | let _mutable_integer = _mutable_integer; | ---------------- | | | first assignment to `_mutable_integer` | help: consider making this binding mutable: `mut _mutable_integer` ... 10 | _mutable_integer = 50; | ^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
- これまで手を動かしてきたところ当たり前な感じがする...Kotlin/Nativeで出てきたフリーズの概念ともちょっと違う気がするし、なぜ別の章立てがされているのか謎。
- 5. Types
- プリミティブ型とユーザー定義型をいろいろ扱いますよ、と。
- 5.1. 型キャスティング
- 型を変換(キャスティング)すると、数字の場合けたあふれが心配...と思っていたら、Rustは自動で警告を出してくれるらしい
- 警告を無視する場合には、以下のコードで警告を抑止できる
// オーバーフローを起こすようなキャスティングによる警告を無視する。 #![allow(overflowing_literals)]
- これがないと以下のようにコンパイルエラーとなる
fn main() { println!("1000 as a u8 is : {}", 1000 as u8); } // コンパイルエラー | 35 | println!("1000 as a u8 is : {}", 1000 as u8); | ^^^^ | = note: `#[deny(overflowing_literals)]` on by default = note: the literal `1000` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `i8`
- 型の暗黙的な変換はできない
fn main() { let decimal = 65.4321_f32; let integer: u8 = decimal; } // 以下のコンパイルエラー Compiling playground v0.0.1 (/playground) error[E0308]: mismatched types --> src/main.rs:10:23 | 10 | let integer: u8 = decimal; | -- ^^^^^^^ expected `u8`, found `f32` | | | expected due to this
- 型変換は明示的に
as u8
などのように行う必要がある
fn main() { let decimal = 65.4321_f32; let integer = decimal as u8; let character = integer as char; println!("Casting: {} -> {} -> {}", decimal, integer, character); // Casting: 65.4321 -> 65 -> A }
- u16をu8にキャストすると以下のようになる
fn main() { println!("1000 is: {}\n[{:b}]", 1000, 1000); // デフォルトはi32 // 1000 is: 1000 // [1111101000] println!("1000 as a u16 is: {}\n[{:b}]", 1000 as u16, 1000 as u16); // 1000 as a u16 is: 1000 // [1111101000] println!("1000 as a u8 is : {}\n[{:b}]", 1000 as u8, 1000 as u8); // 1000 as a u8 is : 232 (1000-256-256-256=232) // [11101000] (8ビットしかないので上位ビットが落ちる) println!("1000 mod 256 is : {} [{:b}]", 1000 % 256, 1000 % 256); // 1000 mod 256 is : 232 println!(" -1 as a i8 is : {}\n[{:b}]", -1i8, -1i8); // -1 as a i8 is : -1 // [11111111] println!(" -1 as a u8 is : {}\n[{:b}]", (-1i8) as u8, (-1i8) as u8); // -1 as a u8 is : 255 (-1 + 256 = 255) // [11111111] }
- 符号付きの型にキャストする場合、以下の2つを行った結果と等しくなる
- 対応する符号なしの型にキャストする。
- 2の補数(two's complement)をとる
fn main() { // 128をu8にキャストすると128となる。128の8ビットにおける補数は -128 println!(" 128 as a i8 is : {} [{:b}]", 128 as i8, 128 as i8); // 128 as a i8 is : -128 [10000000] // 1000 as u8 -> 232 println!("1000 as a u8 is : {} [{:b}]", 1000 as u8, 1000 as u8); // 1000 as a u8 is : 232 [11101000] // 232の8ビットにおける補数は -24 println!(" 232 as a i8 is : {} [{:b}]", 232 as i8, 232 as i8); // 232 as a i8 is : -24 [11101000] // よって以下もおなじ結果 println!("1000 as a i8 is : {} [{:b}]", 1000 as i8, 1000 as i8); // 1000 as a i8 is : -24 [11101000] }
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
久しぶりに2の補数とか出てくると脳みそが疲れる...。
今週のプルリクエストはこちら。