Shanraq.org Shanraq.org
Кортеж: два результата одной функции
IT

Rust: с нуля до своего органайзера Урок 26 из 40

Кортеж: два результата одной функции

Урок 26. Вернуть название и длительность задачи вместе, не смешав их значения.

Текст переведён с помощью ИИ.

Предварительно: уроки 9, 14, 19 и 22. Если возврат значения функции забылся, повторите урок 14.

Образ и опорная карта

На карточке задачи написаны название и число минут. Карточка одна, но у неё два места с разным содержимым. Кортеж — одно значение из нескольких элементов в заданном порядке; элементы могут иметь разные типы. Его длина и тип каждого места известны при компиляции. Образ ограничен: на бумажной карточке места можно произвольно переименовать, а у кортежа места обозначаются позициями. Если важны имена полей, в следующем уроке создадим структуру.

Два значения → скобки и запятая → один кортеж → возврат → разбор на имена. Сначала воспроизведите цепочку без кода. Запись (String, u32) означает тип кортежа: на первом месте владеющее название String, на втором — целое число u32. Запись (title, minutes) создаёт такое значение. Запятая разделяет места; круглые скобки собирают их в одно. Порядок имеет значение: (u32, String) — другой тип.

Возвращаем пару

Сохраните прежний src/main.rs проекта organizer, замените файл целиком и запустите cargo run в папке с Cargo.toml. Других файлов и зависимостей не нужно. Сначала предскажите результат без сообщений Cargo.

У функции first_task после стрелки -> указан один возвращаемый тип (String, u32). Последняя строка без ; возвращает кортеж. В let (title, minutes) = first_task(); запись слева разбирает кортеж: первый элемент получает имя title, второй — minutes. Это называют распаковкой; она связывает места с именами, а не создаёт два независимых результата функции.

fn first_task() -> (String, u32) {
    let title = String::from("Чтение");
    let minutes = 20;
    (title, minutes)
}

fn main() {
    let (title, minutes) = first_task();
    println!("{title}: {minutes} мин");
}
Чтение: 20 мин

String перешёл из функции в кортеж и затем в title; это правило владения из урока 19. Число u32 допускает копирование. Кортеж удобен для короткого промежуточного результата, когда значение каждого места ясно рядом с кодом.

Позиции и граница образа

Если нужен один элемент, после имени кортежа ставят точку и номер места: .0 — первое, .1 — второе. Нумерация начинается с нуля, как индексы массива. В отдельном примере ниже _u32 после 25 явно задаёт тип числа; урок 10 уже разбирал числовые типы. true — логическое значение из урока 11. Кортеж хранит число и флаг о том, хватило ли времени.

fn main() {
    let report = (25_u32, true);
    println!("Минут: {}", report.0);
    println!("Успели: {}", report.1);
}
Минут: 25
Успели: true

Здесь оба элемента копируются при чтении. Если же взять String через .0 из кортежа, владение строкой может перейти к новой переменной; это не способ бесплатно скопировать текст. Кортеж из двух элементов не имеет места .2. Этот отдельный пример намеренно не компилируется с E0609:

fn main() {
    let report = (20_u32, true);
    println!("{}", report.2);
}

Не путайте (20, true) с массивом [20, true]: массив требует одного типа элементов, а кортеж допускает разные. Пустые скобки () из урока 14 обозначают кортеж без элементов и единичное значение; одна запятая в (20,) создаёт кортеж с одним элементом, в отличие от просто (20) — числа в скобках.

Восстановите карту

  1. Почему функция с типом (String, u32) всё же возвращает одно значение?
  2. Какое место берёт .1?
  3. Чем (20,) отличается от (20)?

Проверьте себя: кортеж — одно составное значение; .1 берёт второе место; запятая делает однокомпонентный кортеж. Закройте страницу и проговорите цепочку «два значения → один кортеж → возврат → разбор».

Задание

Обязательное. Напишите plan() -> (String, u32), которая возвращает Прогулка и 30. В main разберите результат на title и minutes, затем выведите Прогулка — 30 мин. Число и название должны приходить из функции, а не из готовой строки в println!.

Проверка границы. Поменяйте порядок элементов в возвращаемом значении, но оставьте объявленный тип прежним. Прочитайте ошибку компилятора и верните порядок назад.

Подсказка

Последним выражением функции сделайте (String::from("Прогулка"), 30). Слева от = в main напишите (title, minutes).

Эталон после попытки

fn plan() -> (String, u32) {
    (String::from("Прогулка"), 30)
}

fn main() {
    let (title, minutes) = plan();
    println!("{title}{minutes} мин");
}
Прогулка — 30 мин

Кортеж сохранил два разных типа вместе, а распаковка дала каждому результату понятное имя. Официальный разбор кортежей.

Предыдущий урок · Оглавление · Следующий урок

Если вы нашли ошибку или опечатку в тексте статьи, то сообщите нам об этом

Комментарии (0)

Пока нет комментариев. Будьте первым.