タプルは、決まった個数の任意の型のデータをひとまとめにする、手軽な方法です。タプルには特定の名前がありません。データ構造に名前を付けると、それはstructになります。タプルのフィールドにも名前がなく、分解するか、位置を指定するかのどちらかでアクセスします。
タプルは常にタプル式で作成します。
// pointless but legal
let unit = ();
// single element
let single_element = ("note the comma",);
// two element
let two_element = (123, "elements can be of differing types");
タプルは任意の個数の要素を持てます。
タプルの要素には、分解によってアクセスできます。これはつまり、タプルの個々の要素に変数名を割り当てて、タプルを消費するということです。
let (elem1, _elem2) = two_element;
assert_eq!(elem1, 123);
タプルの要素には、数値の位置インデックスによってもアクセスできます。インデックスは、いつもどおり0から始まります。
let notation = single_element.0;
assert_eq!(notation, "note the comma");
タプル構造体も扱うことになります。通常の構造体と同じく、これらは名前を持った型です。通常の構造体と違うのは、フィールドが無名である点です。その構文は通常のタプルの構文とよく似ています。分解と位置によるアクセスのどちらも使えます。
struct TupleStruct(u8, i32);
let my_tuple_struct = TupleStruct(123, -321);
let neg = my_tuple_struct.1;
let TupleStruct(byte, _) = my_tuple_struct;
assert_eq!(neg, -321);
assert_eq!(byte, 123);
無名タプルのフィールドは、常にすべて公開されています。ただし、タプル構造体のフィールドにはそれぞれ可視性があり、標準の構造体のフィールドと同じく、既定では非公開です。標準の構造体と同じように、pub修飾子を使えばフィールドを公開できます。
// fails due to private fields
mod tuple { pub struct TupleStruct(u8, i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }
// succeeds: fields are public
mod tuple { pub struct TupleStruct(pub u8, pub i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }
低消費電力の組み込みシステムを対象としたゲームに取り組んでいます。ここでは、ゲームの他の部分から使われる便利な関数をいくつか書く必要があります。
商とは、割り算の結果のことです。
fn divmod(dividend: i16, divisor: i16) -> (i16, i16)
例:
assert_eq!(divmod(10, 3), (3, 1));
上司の話では、これは画面バッファの最適化に役立つそうです。
イテレーターとは、Iteratorトレイトで定義されたメソッドを備えたものです。このドキュメントがかなり充実しているのは、多くのメソッドが用意されているからです。ここでは、特に関係の深い性質を挙げます。
(i, val)を返すenumerateメソッドがありますfilterメソッドがありますmapメソッドがありますこの関数はどんな種類のイテレーターでも動作するので、単なる要素ではなくトレイトのインスタンスであることを示すためにimplを使います。同様に、<Item=T>という構文は、イテレーターが生み出す要素の種類が何であっても構わない、という意味にすぎません。この関数は、どんなイテレーターの偶数番目の要素でも取り出すことができます。
fn evens<T>(iter: impl Iterator<Item=T>) -> impl Iterator<Item=T>
例:
let mut even_ints = evens(0_u8..);
assert_eq!(even_ints.next(), Some(0));
assert_eq!(even_ints.next(), Some(2));
assert_eq!(even_ints.next(), Some(4));
assert_eq!(even_ints.next(), Some(6));
let mut evens_from_odds = evens(1_i16..);
assert_eq!(evens_from_odds.next(), Some(1));
assert_eq!(evens_from_odds.next(), Some(3));
assert_eq!(evens_from_odds.next(), Some(5));
assert_eq!(evens_from_odds.next(), Some(7));
マッピングを便利にするために、タプル構造体Positionが用意されています。
struct Position(i16, i16);
Positionに、原点(Position(0, 0))からのその位置のマンハッタン距離を返すメソッドmanhattanを実装する必要があります。
impl Position {
fn manhattan(&self) -> i16
}
例:
assert_eq!(Position(3, 4).manhattan(), 7);