Кортеж (tuple) представляет способ группировки данных разных типов в один составной тип. Кортежи имеют фиксированный тип в соответствии с вложенными данными. После определения кортежа его размер нельзя ни уменьшить, ни увеличить.
Формальный синтаксис определения кортежа:
let tuple = (значение1, значение2, ... значениеN);
Кортеж определяется в круглых скобках, внутри которых через запятую перечисляются составляющие кортеж значения.
Определение простейшего кортежа:
let user = ("Tom", 36, 1.78);
Здесь переменная user
представляет кортеж, который состоит из трех элементов.
В примере выше тип элементов кортежа выводится автоматически, но также мы можем явно задать их типы:
let user: (&str, u8, f32) = ("Tom", 36, 1.78);
То есть в данном случае кортеж имеет тип (&str, u8, f32)
, а это значит, что первый его элемент должен представлять строку,
второй элемент - число типа u8
, а третий - число с плавающей точкой типа f32
.
После объявления кортежа мы можем обращаться к его элементам в виде:
название_кортежа.индек_элемента
После названия кортежа через точку указывается индекс элемента кортежа, при этом индексация начинается с нуля. Например:
fn main(){ let user: (&str, u8, f32) = ("Tom", 36, 1.78); println!("Имя: {}", user.0); println!("Возраст: {}", user.1); println!("Рост: {}", user.2); }
Консольный вывод:
Имя: Tom Возраст: 36 Рост: 1.78
Также мы можем изменять элементы кортежа, если его переменная определена с ключевым словом mut:
fn main(){ let mut user: (&str, u8, f32) = ("Tom", 36, 1.78); user.0 = "Bob"; println!("Имя: {}", user.0); // Bob }
Rust предоставляет такую возможность, как декомпозиция (destructuring) кортежа. Например, мы могли бы следующим образом присвоить значения кортежа переменным:
fn main(){ let user = ("Tom", 36, 1.78); // присваиваем переменным значения кортежа let name = user.0; let age = user.1; let height = user.2; println!("Имя: {}", name); println!("Возраст: {}", age); println!("Рост: {}", height); }
Но декомпозиция позволяет сократить код:
fn main(){ let user = ("Tom", 36, 1.78); // декомпозиция кортежа на переменные let (name, age, height) = user; println!("Имя: {}", name); println!("Возраст: {}", age); println!("Рост: {}", height); }
Но, возможно, нам нужны не все данные из кортежа. Например, нам не нужно получать рост человека. Тем не менее мы не можем написать, например, так:
let (name, age) = user; // !Ошибка
Нам обязательно надо указать столько же переменных, сколько значений в кортеже. Однако если какое-то значение нам не нужно, мы можем вместо соответствующей переменной указать прочерк:
let (name, age, _) = user;
Для сравнения кортежей применяется операция ==
. Кортежи считаются равными, если равны их соответствующие значения. Пример сравнения кортежа:
fn main() { let user = ("Tom", 36); if ("Tom", 36) == user { println!("name: Tom, age: 36"); } }
Как и любой другой тип, кортеж может выступать параметром функции. Например:
fn display((name, age):(&str, i32)){ println!("name: {} age:{}", name, age); } fn main(){ let tom = ("Tom", 36); display(tom); }
Здесь функции display()
принимает кортеж, причем первый элемент этого кортежа представляет тип &str
или строку, а второй элемент - тип i32
.
И также функция может возвращать кортеж:
fn get_default_point() -> (i32, i32){ (4, 25) } fn main(){ let (x, y) = get_default_point(); println!("x: {} y:{}", x, y); }
Здесь функция get_default_point()
возврашает кортеж, первый и второй элементы которого представляют тип i32
.