Пример: список

Реализовать fmt::Display для структуры, в которой каждый элемент должен обрабатываться последовательно, не так-то просто. Проблема в том, что write! каждый раз возвращает fmt::Result. Для правильного обращения с этим необходимо обрабатывать все результаты. Для этой цели Rust предоставляет оператор ?.

Использование ? для write! выглядит следующим образом:

// Попробуй исполнить `write!`, чтобы узнать, вернется ли ошибка. Если будет ошибка — верни её.
// Если нет, то продолжи.
write!(f, "{}", value)?;

С помощью оператора ? реализация fmt::Display для Vec довольно простая:

use std::fmt; // Импортируем модуль `fmt`.

// Определяем структуру с именем `List`, которая хранит в себе `Vec`.
struct List(Vec<i32>);

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Получаем значение с помощью индекса кортежа
        // и создаём ссылку на `vec`.
        let vec = &self.0;

        write!(f, "[")?;

        // Пройдёмся по каждому `v` в `vec`.
        // Номер итерации хранится в `count`.
        for (count, v) in vec.iter().enumerate() {
            // Для каждого элемента, кроме первого, добавим запятую
            // до вызова `write!`. Используем оператор `?` или `try!`,
            // чтобы вернуться при наличии ошибок.
            if count != 0 { write!(f, ", ")?; }
            write!(f, "{}", v)?;
        }

        // Закроем открытую скобку и вернём значение `fmt::Result`
        write!(f, "]")
    }
}

fn main() {
    let v = List(vec![1, 2, 3]);
    println!("{}", v);
}

Задание

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

[0: 1, 1: 2, 2: 3]

Смотрите также:

for, ref, Result, struct, ?, и vec!