トラック
/
Rust
Rust
/
演習
/
低電力組み込みゲーム
低電力組み込みゲーム

低電力組み込みゲーム

学習演習

はじめに

タプルは、決まった個数の任意の型のデータをひとまとめにする、手軽な方法です。タプルには特定の名前がありません。データ構造に名前を付けると、それは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); }

説明

低消費電力の組み込みシステムを対象としたゲームに取り組んでいます。ここでは、ゲームの他の部分から使われる便利な関数をいくつか書く必要があります。

1. 割り算の商と余りを計算する

商とは、割り算の結果のことです。

fn divmod(dividend: i16, divisor: i16) -> (i16, i16)

例:

assert_eq!(divmod(10, 3), (3, 1));

2. イテレーターから偶数番目の要素を選ぶ

上司の話では、これは画面バッファの最適化に役立つそうです。

イテレーターとは、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));

3. 原点から見た位置のマンハッタン距離を計算する

マッピングを便利にするために、タプル構造体Positionが用意されています。

struct Position(i16, i16);

Positionに、原点(Position(0, 0))からのその位置のマンハッタン距離を返すメソッドmanhattanを実装する必要があります。

impl Position {
    fn manhattan(&self) -> i16
}

例:

assert_eq!(Position(3, 4).manhattan(), 7);
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Rust Exercism

低電力組み込みゲームを始める準備はできましたか?

Exercismに登録すれば、99個の演習、そして本物の人間によるメンタリングとともに、Rustを学んでマスターできます。すべて無料です。