Tupel sind eine einfache Möglichkeit, eine feste Anzahl beliebiger Datentypen zusammenzufassen. Ein Tupel hat keinen bestimmten Namen; sobald du einer Datenstruktur einen Namen gibst, wird daraus ein struct. Die Felder eines Tupels haben keine Namen; auf sie greifst du über Destrukturierung oder über ihre Position zu.
Tupel werden immer mit einem Tupelausdruck erstellt:
// 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");
Tupel können eine beliebige Anzahl von Elementen haben.
Du kannst auf die Elemente eines Tupels durch Destrukturierung zugreifen. Das bedeutet, dass du den einzelnen Elementen des Tupels Variablennamen zuweist und das Tupel dabei verbrauchst.
let (elem1, _elem2) = two_element;
assert_eq!(elem1, 123);
Du kannst auf die Elemente eines Tupels auch über ihren numerischen Positionsindex zugreifen. Die Indexierung beginnt wie immer bei 0.
let notation = single_element.0;
assert_eq!(notation, "note the comma");
Außerdem wirst du mit Tupelstrukturen arbeiten. Wie normale Strukturen sind sie benannte Typen; anders als normale Strukturen haben sie anonyme Felder. Ihre Syntax ist der normalen Tupelsyntax sehr ähnlich. Du darfst sowohl Destrukturierung als auch den Zugriff über die Position verwenden.
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);
Alle Felder anonymer Tupel sind immer öffentlich. Die Felder von Tupelstrukturen haben dagegen jeweils eine eigene Sichtbarkeit, die standardmäßig privat ist, genau wie die Felder normaler Strukturen. Mit dem Modifizierer pub kannst du die Felder öffentlich machen, genau wie bei einer normalen Struktur.
// 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); }
Du arbeitest an einem Spiel für ein stromsparendes eingebettetes System und musst mehrere Hilfsfunktionen schreiben, die andere Teile des Spiels verwenden werden.
Der Quotient ist das Ergebnis einer Division.
fn divmod(dividend: i16, divisor: i16) -> (i16, i16)
Beispiel:
assert_eq!(divmod(10, 3), (3, 1));
Damit lässt sich später eine Optimierung des Bildschirmpuffers umsetzen, verspricht zumindest dein Chef.
Iteratoren stellen die Methoden bereit, die im Iterator-Trait definiert sind. Diese Dokumentation ist recht umfangreich, weil sie viele Methoden anbieten. Hier sind die wichtigsten Eigenschaften:
enumerate-Methode, die für jeden Wert ein Tupel (i, val) zurückgibtfilter-Methode, die eine Closure verwendet, um zu entscheiden, ob ein Element des Iterators ausgegeben wirdmap-Methode, die eine Closure verwendet, um Elemente des Iterators zu verändernWeil deine Funktion mit jeder Art von Iterator arbeiten kann, verwendet sie impl, um anzuzeigen, dass es sich um eine Trait-Instanz und nicht um ein einfaches Element handelt. Ebenso bedeutet die Syntax <Item=T> nur, dass es keine Rolle spielt, welche Art von Element der Iterator erzeugt; deine Funktion kann die geraden Elemente jedes Iterators liefern.
fn evens<T>(iter: impl Iterator<Item=T>) -> impl Iterator<Item=T>
Beispiele:
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));
Damit du bequem mit Koordinaten arbeiten kannst, hast du ein Tupel-Struct Position:
struct Position(i16, i16);
Du musst eine Methode manhattan auf Position implementieren, die die Manhattan-Distanz dieser Position vom Ursprung (Position(0, 0)) zurückgibt.
impl Position {
fn manhattan(&self) -> i16
}
Beispiel:
assert_eq!(Position(3, 4).manhattan(), 7);
Melde dich bei Exercism an, um Rust mit 99 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.