配列 (array)
配列の基本
Rust の配列は、多くの言語と同様に []
を使って生成することができます。
配列の要素の型はすべて同一である必要があり、配列サイズ(要素数)は不変です。
要素数をあらかじめ固定できない場合は、配列の代わりに ベクター (Vec) 型 を使います。
let arr = [0, 1, 2]; // [i32; 3]
let arr = ["AAA", "BBB", "CCC"]; // [&str; 3]
let arr = [true, false, true]; // [bool; 3]
要素の参照は、C/C++ と同様に 0 始まりのインデックス指定で行えます (arr[0]
)。
配列のサイズ(要素数)は arr.len()
で取得できます。
let arr = ['あ', 'い', 'う'];
println!("{}, {}, {}", arr[0], arr[1], arr[2]); // あ, い, う
println!("len={}", arr.len()); // len=3
可変配列 (mutable array)
要素を変更可能にしたいときは、次のように let mut
で配列を定義します。
可変というのは、ある位置の値を変更できるという意味であって、配列のサイズや型を変更することはできないことに注意してください。
let mut arr = ["AAA", "BBB", "CCC"];
arr[1] = "XXX";
println!("{:?}", arr); //=> ["AAA", "XXX", "CCC"]
次のように、すべての要素をまとめて入れ替えることもできますが、同じ型&サイズの配列を代入しなければいけません。
let mut arr = [1, 2, 3]; // [i32; 3] 型の変数
println!("{:?}", arr); //=> [1, 2, 3]
arr = [4, 5, 6]; // [i32; 3] 型の配列であれば代入できる
println!("{:?}", arr); //=> [4, 5, 6]
配列のサイズを指定して初期化
セミコロン (;
) を使った特殊な構文を使うと、要素の初期値とサイズを指定して配列を生成することができます。
タプル (tuple)
タプルの基本
タプルは任意の数のフィールドを持つことができる複合型です。 配列と似ていますが、タプルでは各フィールドの型が異なっていても構いません。
let t = ("AAA", 100, 'x'); // 型は推測されるので下記と同様
let t: (&str, i32, char) = ("AAA", 100, 'x');
各フィールドを参照するには、t.0
、t.1
、t.2
のように、ドットの後にインデックス番号を指定します。
配列とは異なり、変数に格納されたインデックス番号を使用することはできません(t.index
のようには書けません)。
println!("{}, {}, {}", t.0, t.1, t.2); //=> AAA, 100, x
// まとめて出力する場合は次のようにすると楽
println!("{:?}", t); //=> ("AAA", 100, x)
可変タプル (mutable tuple)
配列と同様、タプルも let mut
を付けて定義することで、各フィールドの値を可変にすることができます。
ただし、各フィールドの「型」は変更できないことに注意してください。
let mut t = ("AAA", 100, 'x');
t.0 = "BBB";
t.1 = 200;
t.2 = 'y';
タプルの分解
次のようにして、タプルの各要素を別々の変数に格納することができます。
let t = ("AAA", 100, 'x');
let (x, y, z) = t; // タプルの分解
println!("{}, {}, {}", x, y, z); //=> AAA, 100, x
空タプル (empty tuple) = ユニット (unit)
Rust では、値がないことを示す型(値)として、空タプル ()
が使われます。
これは、1 つもフィールドを持たないタプルで、値も型も ()
と記述します。
C/C++ void
に相当するもので、ユニット (unit) とも呼ばれます。
戻り値を持たない関数は空タプルを返します。
空のブロック ({}
) も空タプルを返します。
次の a
、b
、c
はすべて空タプルになります。
let a = (); // 明示的な空タプル
let b = {}; // 評価後の値がないブロック
let c = (|| {})(); // 戻り値のないクロージャの呼び出し
println!("{:?} {:?} {:?}", a, b, c); //=> () () ()
戻り値を持たない関数を定義するとき戻り値の型は省略できますが、明示的に -> ()
と記述することもできます。
// 関数 foo と bar は戻り値を持たない (= 空タプルを返す)
fn foo() {}
fn bar() -> () {}
println!("{:?}", foo()); // ()
println!("{:?}", bar()); // ()