前回の Variable Bindings と Functionsに続いてhttps://doc.rust-lang.org/bookをやっていきます。
今日は4.3. Primitive Typesからです。
4.3. Primitive Types
Primitive Types
primitiveな型は全て、Rust言語に組み込みの型です。 構成はJavaなどの他の言語と似ています。char型がUnicodeの4byteというのが、思い切ってるというか新しい言語ならではだな、と感じました。
Booleans
bool
は真偽値の型です。true
かfalse
どちらかの値を持ちます。
fn main() { let x = true; // 型注釈なしだと型推論される let y: bool = false; // 型注釈あり if x { println!("x={}, y={}", x, y); } //=> x=true, y=false }
char
char
型は、ユニコードのスカラ値です。- シングルクォート(
'
)で囲んで表記します。 - Rustの
char
型は、1byteではなく4byteです。 他の言語と違うところです。
// ASCIIはもちろん、 let x = 'x'; // ユニコードなので絵文字もいけるよ! let two_hearts = '💕';
Numeric types
Rustにはたくさんの数値型があります。
数値型の型名は次のような構成になっています。
- 最初の1文字が分類。
- 2文字目以降がサイズ。
例えば、i32
型なら、32bit符号付き整数を指します。
8bit | 16bit | 32bit | 64bit | 可変長 | |
---|---|---|---|---|---|
符号付き整数 (integer) | i8 |
i16 |
i32 |
i64 |
isize |
符号無し整数 (unsigned integer) | u8 |
u16 |
u32 |
u64 |
usize |
浮動小数点 (float) | - | - | f32 |
f64 |
- |
Javaにはprimitiveな符号無し数値型は存在しないですよね。 あれば便利そうだけど。 C#の整数型の一覧やMySQLの整数型には、符号無しの数値型があります。 近いですね。
Signed and Unsigned
型名の1文字目は、符号付きか符号無しかを表しています。
例えば、
i8
型は-128
〜127
の範囲を表現し、
u8
型は0
〜255
の範囲を表現します。
Fixed-size types
型名の2文字目以降が数字になっている数値型は、固定長の数値型です。
例えばi64
なんかは64bit固定長です。
Variable-size types
可変長の数値型も2つ存在します。
isize
とusize
です。
Floating-point types
f32
とf64
はIEEE-754準拠の単精度と倍精度の浮動小数点数です。
Arrays
- 配列型は、同種の型の要素からなる固定長のリストです。
- 配列型はデフォルトではイミュータブルです。
- ミュータブルにするにはやはり
let
を使います。 - 配列の型注釈は
[T; N]
のように表記します。
fn main() { // 型推論により a1: [i32; 3] つまり「i32型の要素が3つ」という型になる。 let a1 = [10, 20, 30]; // mutを使えばミュータブルになるのは変わらず。 let mut a2 = [10, 20, 30]; // [i32; 100]型に推論され、全ての要素が 0 で初期化される let a3 = [0; 100]; // サイズ取得の len() メソッド println!("a3.len()={}", a3.len()); //=> a3.len()=100 // 添字アクセス println!("The second number is: {}", a1[1]); //=> The second number is: 20 // 範囲外に添字アクセス println!("The fourth number is: {}", a2[3]); //=> ランタイムエラー }
最後のエラーは、ラインタイム時です。 コンパイル時にチェックされるわけではないようですね。
thread '<main>' panicked at 'index out of bounds: the len is 3 but the index is 3', src/main.rs:20 note: Run with `RUST_BACKTRACE=1` for a backtrace. Process didn't exit successfully: `target/debug/foo` (exit code: 101)
Slices
slice
は別のデータ構造への参照(あるいはビュー)です。slice
によって、例えば「ある文字列の最初の1行」のような、配列の特定の部分への効率的なアクセスが可能になります。- イミュータブルにもミュータブルにもできます。
- 内部的には、該当のデータの始点のポインタとその長さで表現されています。
str
- Rustの
str
型は、primitiveな文字列型です。 &str
のような参照に隠されたかたちで利用されることが多いようです。
Tuples
- タプルは、順序のある固定長のリストです。
- タプルの型宣言はタプル表記と同様に
(
と)
内にカンマ区切りで、要素の型を列挙します。 - タプルは異種混合(heterogeneous)の型です。 つまり、異なる型を要素に保持できます。同種の型の要素を保持する配列とは異なります。
fn main() { // タプルを変数に束縛 let x = (10, "hello"); // 型注釈を明示することももちろん可能 let y: (i32, &str) = x; // 要素を分配束縛するのにタプル表記が使える。 let (one, two, three) = (10, "hello", 123); println!("{}, {}, {}", one, two, three); //=> 10, hello, 123 // 要素が1つだけのタプルは、ケツカンマが必要 let (z,) = (999,); println!("{}", z); //=> 999 // これは、要素が1つのタプルとはみなされない。コンパイルエラーになる。 // let (z) = (999); }
Tuple Indexing
タプルも配列みたいに添字アクセスができるが、添字の記法が異なります。
fn main() { let t = (111, 222, "three"); // タプルの添字アクセス println!("{}", t.0); //=> 111 // 範囲外のアクセスはコンパイルエラー // println!("{}", t.3); }
Functions
関数にも型があります。
例えば、「32bit符号付き整数を1つ受け取って、32bit符号付き整数を1つ返す関数」の型はfn(i32) -> i32
です。
fn main() { fn increment(x: i32) -> i32 { x + 1 } let x = increment; println!("{}", x(100)); //=> 101 // もちろん型注釈を明示してもよい let y: fn(i32) -> i32 = increment; println!("{}", y(200)); //=> 201 }
Comments
行コメントとdocコメントの2種類があります。
行コメントは//
以降行末までです。
docコメントはマークダウン記法をサポートします。*1
また、2種類の記法があります。
///
と//!
です。
//!
は主にcrateのルート(lib.rs)やモジュールのルート(mod.rs)内で使用されるようです。
rustdoc
というツールでdocコメントからドキュメントを生成することができます。
*1:rustdocがdocコメント内のマークダウンをサポートするという意味なのではないかと思います。