Пример: список
Реализовать 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]