S-JIS[2024-09-16] 変更履歴

Rust基本データ型メモ

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
b'A'
 
u16 符号なし16ビット整数 123  
u32 符号なし32ビット整数 123  
u64 符号なし64ビット整数 123  
usize 符号なしアーキテクチャー依存整数 123  
浮動小数型 f32 単精度浮動小数点数 123.0
1e3
float
f64 倍精度浮動小数点数 double
論理値型 bool 論理値 true
false
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)
(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つの値を持っている)

したがって、ユニット型を返す関数は、常に同じ値しか返さないことになる。
これは実質的に、値に意味がないのと同じ。
なので、「値を返さない関数」は、実はユニット型を返すようになっている。

never型


let a: () = ();	// 「: ()」はユニット型を表し、「=」の後の「()」は値を表している

Rustへ戻る / 技術メモへ戻る
メールの送信先:ひしだま