Реализовать fmt::Display
для структуры, в которой каждый элемент должен обрабатываться последовательно не так то просто. Проблема в том, что write!
каждый раз возвращает fmt::Result
.
Правильная обработка fmt::Result
требует работы с каждым результатом.
Для подобных случаев Rust предоставляет макрос try!
.
Использование try!
для write!
выглядит следующим образом:
// Попробуй исполнить `write!`, чтобы узнать, вернется ли ошибка. Если ошибка, верни ее.
// Если нет, то продолжи.
try!(write!(f, "{}", value));
С помощью макроса try!
реализация 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 { // Разыменуем `self` и создадим связь с `vec` // с помощью ссылки. let List(ref vec) = *self; try!(write!(f, "[")); // Пройдемся по каждому `v` в `vec`. // Номер итерации хранится в `count`. for (count, v) in vec.iter().enumerate() { // Для каждого элемента, кроме первого, добавим запятую // до вызова `write!`. Используем `try!`, чтобы вернуться при наличие ошибок. if count != 0 { try!(write!(f, ", ")); } try!(write!(f, "{}", v)); } // Закроем открытую скобку и вернем значение `fmt::Result` write!(f, "]") } } fn main() { let v = List(vec![1, 2, 3]); println!("{}", v); }
Попробуйте изменить программу так, чтобы индекс элемента так же выводился в консоль. Новый вывод должен выглядеть примерно вот так:
[0: 1, 1: 2, 2: 3]