Rust на примерах

1.2.2.1 Тест: Список

Реализовать 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]

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

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