Кортежі - це легкий спосіб згрупувати докупи фіксований набір даних довільних типів. Кортеж не має
конкретного імені; коли ми даємо структурі даних імʼя, вона стає 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. Ця документація досить обширна, бо ітератори надають багато методів; ось найважливіші властивості:
enumerate, який повертає кортеж (i, val) для кожного значення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);
Потрібно реалізувати метод manhattan у Position, який повертає манхеттенську відстань цієї позиції від початку координат (Position(0, 0)).
impl Position {
fn manhattan(&self) -> i16
}
Приклад:
assert_eq!(Position(3, 4).manhattan(), 7);