今日もやっていきます。型のお話です。
Rustの型
概要
Rustは静的型付け言語であり、暗黙的な型変換をほとんど行わない強い型付けを行う言語です。強い型付け言語と言えばPythonやJavaなどがありますが、その中でも特に厳密な型の整合性を要求します。
int + float → エラー?
例えば、以下のようなコードはそもそもコンパイルが通りません。
assert_eq!(1 + 1.2, 2.2);
Compiling playground v0.0.1 (/playground) error[E0277]: cannot add a float to an integer --> src/main.rs:2:18 | 2 | assert_eq!(1 + 1.2, 2.2); | ^ no implementation for `{integer} + {float}` | = help: the trait `std::ops::Add<{float}>` is not implemented for `{integer}`
intとfloatを足し算する時であっても、暗黙的に型変換を行いません。正しくは以下のようにas
を用いてキャストを行います。
assert_eq!(1 as f32 + 1.2, 2.2);
if x {} → エラー?
この他にも、ifやwhileなどの条件式は必ずbool型である必要があります。以下のような記述はコンパイルエラーになります。
let x:u64 = 3; if x { print!("true"); }
Compiling playground v0.0.1 (/playground) error[E0308]: mismatched types --> src/main.rs:3:4 | 3 | if x { | ^ expected bool, found u32
正しくはこう
let x:u64 = 3; if x > 0 { print!("true"); }
型いろいろ
変数の定義
変数名の後に型を書いて定義します。
let x: u64 = 3; // 64bit符号なし整数 let y: i64 = -2; //符号あり
型推論
rustには型推論の機構が備わっており、上の変数定義は以下のように書くこともできます。
let x = 3;
この場合、xはi32(符号あり32bit整数)と推論されます。
整数リテラル
整数リテラルには2u16
のように後ろに型をつけます。なんだかキモいですね。2_u16
のようにアンダースコアで区切っても良いです。整数はpow
やabs
のようなメソッドを持ちますが、その際には型を明示する必要があります。
assert_eq!(2u16.pow(2), 4); assert_eq!((-4i32).abs(), 4); //.abs()の方が優先度が高いので括弧で囲む
文字
文字はchar型です。C言語とは異なりUnicodeの1文字を表現するので、32bitの値を持ちます。シングルクオートで囲むことで表現できます。
タプル
タプルは配列とは異なり異なる型の値を格納することができます。
let t = ("sheep", 1); // t.0, t.1としてアクセス
定数アクセスしかできないという制約があるため、iを変数として、t.iのようなアクセスはできません。
今日はSecHack365の説明会などで時間があまり取れなかったので、この辺りで。