第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の補数とか出てくると脳みそが疲れる...。
今週のプルリクエストはこちら。