Les tuples sont un moyen simple de regrouper un ensemble fixe de données de types arbitraires. Un tuple n'a pas de nom particulier ; nommer une structure de données en fait un struct. Les champs d'un tuple n'ont pas de nom ; on y accède par déstructuration ou par position.
Un tuple est toujours créé à l'aide d'une expression de tuple :
// 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");
Un tuple peut contenir un nombre arbitraire d'éléments.
Il est possible d'accéder aux éléments d'un tuple par déstructuration. Cela consiste simplement à affecter des noms de variables aux différents éléments du tuple, ce qui le consomme.
let (elem1, _elem2) = two_element;
assert_eq!(elem1, 123);
Il est également possible d'accéder aux éléments d'un tuple par un indice de position numérique. L'indexation, comme toujours, commence à 0.
let notation = single_element.0;
assert_eq!(notation, "note the comma");
On te demandera aussi de travailler avec des structures tuples. Comme les structures classiques, ce sont des types nommés ; contrairement aux structures classiques, leurs champs sont anonymes. Leur syntaxe est très proche de celle des tuples classiques. Il est possible d'utiliser à la fois la déstructuration et l'accès par position.
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);
Tous les champs d'un tuple anonyme sont toujours publics. En revanche, les champs d'une structure tuple possèdent leur propre visibilité, qui est privée par défaut, tout comme les champs des structures classiques. Tu peux rendre les champs publics à l'aide du modificateur pub, exactement comme dans une structure classique.
// 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); }
Tu travailles sur un jeu destiné à un système embarqué à faible consommation et tu dois écrire plusieurs fonctions utilitaires qui seront utilisées par d'autres parties du jeu.
Un quotient est le résultat d'une division.
fn divmod(dividend: i16, divisor: i16) -> (i16, i16)
Exemple :
assert_eq!(divmod(10, 3), (3, 1));
Cela sera utile pour activer une optimisation du tampon d'écran, promet ton patron.
Les itérateurs sont des éléments qui exposent les méthodes définies par le trait Iterator. Cette documentation est assez complète, car ils offrent de nombreuses méthodes ; voici les propriétés les plus pertinentes :
enumerate qui renvoie un tuple (i, val) pour chaque valeurfilter qui utilise une fermeture pour déterminer s'il faut produire un élément de l'itérateurmap qui utilise une fermeture pour modifier les éléments de l'itérateurComme ta fonction peut fonctionner avec n'importe quel type d'itérateur, elle utilise impl pour signifier qu'il s'agit d'une instance de trait plutôt que d'un simple élément. De même, la syntaxe <Item=T> signifie simplement que le type d'élément produit par l'itérateur n'a pas d'importance ; ta fonction peut produire les éléments pairs de n'importe quel itérateur.
fn evens<T>(iter: impl Iterator<Item=T>) -> impl Iterator<Item=T>
Exemples :
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));
Pour faciliter la cartographie, tu disposes d'une structure tuple Position :
struct Position(i16, i16);
Tu dois implémenter une méthode manhattan sur Position qui renvoie la distance de Manhattan de cette position par rapport à l'origine (Position(0, 0)).
impl Position {
fn manhattan(&self) -> i16
}
Exemple :
assert_eq!(Position(3, 4).manhattan(), 7);
Inscris-toi sur Exercism pour apprendre et maîtriser Rust avec 99 exercices, et un vrai mentorat humain, le tout gratuitement.