Rustの基本データ型のメモ。
|
Rustの基本データ型はスカラー型(scalar)と複合型(compound)の2種類ある。
スカラー型は単独の値を表す。(整数・浮動小数点数・論理値・文字)
複合型は、タプルと配列。
全てのスカラー型はCopyトレイトが実装されているので、値のコピーが出来る。
値のコピーが出来るということは、変数に代入したり関数(やメソッド)へ渡したり関数から返したりする際に値をコピーできるということなので、所有権を気にする必要が無い(所有権の移動を伴わない)。
タプルは、保持している全ての値の型がCopyトレイトを実装している場合はCopyになる。
配列は、要素の型がCopyトレイトを実装している場合はCopyになる。
Rustで値のコピーが出来る条件(Copyトレイトを実装できる条件)のひとつは、コンパイル時にデータのサイズが確定できること、らしい。
スカラー型はデータサイズが決まっている。
タプルや配列は要素数は固定なので、保持している値のサイズも固定ならデータサイズが決定できる、ということだろう。
名称 | 型名 | 説明 | リテラルの例 | Java相当 |
---|---|---|---|---|
整数型 | i8 |
符号あり8ビット整数 | 123 |
byte |
i16 |
符号あり16ビット整数 | 123 |
short |
|
i32 |
符号あり32ビット整数 | 123 |
int |
|
i64 |
符号あり64ビット整数 | 123 |
long |
|
isize |
符号ありアーキテクチャー依存整数 | 123 |
||
u8 |
符号なし8ビット整数 | 123 |
||
u16 |
符号なし16ビット整数 | 123 |
||
u32 |
符号なし32ビット整数 | 123 |
||
u64 |
符号なし64ビット整数 | 123 |
||
usize |
符号なしアーキテクチャー依存整数 | 123 |
||
浮動小数型 | f32 |
単精度浮動小数点数 | 123.0 |
float |
f64 |
倍精度浮動小数点数 | double |
||
論理値型 | bool |
論理値 | true |
boolean |
文字型 | char |
文字(Unicodeのスカラー値・32ビット) | 'あ' |
char |
アーキテクチャー依存整数(isize・usize)は、いわゆるポインターサイズ。
64ビットマシンなら64ビット、32ビットマシンなら32ビットになる。
println!("isize.bytes = {}", size_of::<isize>());
整数型の場合、十進数の他に二進数・八進数・十六進数表記が出来る。
また、数字と数字の間にアンダースコア「_」を入れることが出来る。
100_000 0b1111_0000 0o777 0xffff
整数型・浮動小数型のリテラルに関しては、末尾に型名を付けて型を明示することも出来る。
0xffu8 -1i8 123u32 123_u32 123i64 // Javaの123L 123f32 // Javaの123f 1.0f32 // Javaの1.0f 123f64 // Javaの123d 123isize
0xffi8
はエラーになる(0xffは255だが、i8は-128〜127の範囲なので)が、asでキャストすれば通る。
0xffu8 as i8
タプルは複数の値をまとめて扱う型。
値の個数は固定で、それぞれの値は異なるデータ型で構わない。
値の個数 | 例 | 備考 | Scala相当 | ||
---|---|---|---|---|---|
リテラル | 型 | リテラル | 型 | ||
0 | () |
() |
→ユニット型 | () |
Unit |
1 | (1,) |
(i32,) |
カンマ無しだと優先する式(「(1+1)*2 」みたいな式)と区別がつかないので、末尾カンマが必須。 |
Tuple1(1) |
(Int,) |
2 | (1, 2) |
(i32, i32) |
値の個数が2個以上の場合、最後の値の末尾にカンマがあっても無視される。 | (1, 2) |
(Int, Int) |
説明 | 例 | Scala相当 |
---|---|---|
タプルからそれぞれの値を取り出すには、タプルに「. 番号」を付ける。 |
let t = (1, 2, 3); println!("t.0 = {}", t.0); |
val t = (1, 2, 3) printf("t._1 = %d\n", t._1) |
タプルからパターンマッチで分解して値を取り出すことが出来る。 (分配(destructuring)というらしい) |
let (a, b, c) = t; println!("a = {}", a); |
val (a, b, c) = t println(s"a = $a") |
let (a, _, _) = t; |
val (a, _, _) = t |
|
let (a, ..) = t; |
配列は同じデータ型の値を複数持つ型。要素数は固定。
配列は角括弧で囲み、カンマ区切りで要素を並べていく。
最後の要素の末尾にカンマがあっても無視される。
配列の型は「[要素の型; 要素数]
」となる。
[1, 2, 4, 8, 16] // 型は[i32; 5] [1, 2, 4, 8, 16,]
Rustの配列の型は要素数まで含んでいるので、要素の型が同じでも要素数が違えば異なる型という扱いになる。
同じ値で埋める場合は「[値; 要素数]
」と書くことが出来る。
[0; 5] // [0, 0, 0, 0, 0]と同じ
要素を取り出すには「配列[番号]
」と書く。
let a = [1, 2, 4, 8, 16]; println!("a0 = {}", a[0]);
for文で要素を取り出すことも出来る。
let a = [1, 2, 4, 8, 16]; for e in a { println!("{}", e); }
Rust By Example 日本語版の基本データ型によると、値の個数が0個のタプルをユニット型と言うらしい。
(ScalaのUnitもそういう扱いだった)
タプルは複合型に属するが、ユニット型はスカラー型なのだそうだ。
Rustのユニット型は「()
」で表される。
ユニット型は唯一の値「()
」だけを持つ。
(例えばboolはtrueとfalseの2つの値を持っている)
したがって、ユニット型を返す関数は、常に同じ値しか返さないことになる。
これは実質的に、値に意味がないのと同じ。
なので、「値を返さない関数」は、実はユニット型を返すようになっている。
let a: () = (); // 「: ()」はユニット型を表し、「=」の後の「()」は値を表している