Какой элемент во вложенной структуре реализует свойство итератора?

#rust #iterator #nested-lists

#Ржавчина #итератор #вложенные списки

Вопрос:

Я смотрю видео об итераторах Rust, и видеохостинг реализует немного более сложную структуру Flatten . По сути, эта Flatten структура содержит элементы, каждый из которых реализует IntoIterator признак, так что каждый элемент внутри Flatten (обратите внимание, что следующий код не является окончательным кодом из видео и используется только для демонстрации моего замешательства):

 pub struct Flatten<O>
{
    outer: O,
}

impl<O> Flatten<O> {
    fn new(iter: O) -> Self {
        Flatten { outer: iter }
    }
}
  

Затем есть часть, в которой Flatten реализуется Iterator признак:

 impl<O> Iterator for Flatten<O>
where
    O: Iterator,
    O::Item: IntoIterator,
{
    type Item = <O::Item as IntoIterator>::Item;
    fn next(amp;mut self) -> Option<Self::Item> {
        self.outer.next().and_then(|inner| inner.into_iter().next())
    }
}
  

Что меня очень смущает, так это то, что когда мы устанавливаем ограничение O::Item: IntoIterator , мы, очевидно, имели в виду, что универсальный тип O имеет элементы, которые реализуют IntoIterator .

Редактировать 1: чтобы уточнить, мое замешательство заключалось в том, что мы сначала сказали это O::Item: IntoIterator , а затем снова указали type Item = <O::Item as IntoIterator>::Item . Являются Item ли s, появляющиеся в этих двух предложениях, относящимися к разным понятиям?

Редактировать 2: думаю, теперь я это понимаю. An Iterator имеет Item , поэтому мы могли бы написать O::Item: IntoIterator . И когда мы определяем type Item = <O::Item as IntoIterator>::Item , мы указываем тип возвращаемого элемента для Flatten , а не для O . Я был смущен синтаксисом и имел некоторое нелогичное понимание.

Комментарии:

1. Я не вижу проблемы, вы никогда не ссылаетесь на голый Item , всегда a Self::Item , O::Item или <O::Item as IntoIterator>::Item . Никакой двусмысленности.

2. Мне трудно понять этот вопрос, в частности, «Является Item ли in Flatten все еще O или сейчас Flatten::O::Item ?» Что именно такое » Item вход Flatten «? И почему это должно быть O ? И что Flatten::O::Item должно быть? Было бы неплохо, если бы вы могли прояснить вопрос.

3. Flatten Кстати, реализация делает что-то довольно странное, и я бы, конечно, не назвал эту операцию «выравниванием».

4. @SvenMarnach Это не окончательная реализация, хост указывает на ошибку позже в видео. Однако OP мог бы включить это в вопрос..

5. @NiklasMohrin Я внес правку, чтобы указать это сейчас. Спасибо.

Ответ №1:

Rust знает, какой элемент выбрать, потому что мы специально говорим ему, что Item выбрать. Мы знаем, что оба Iterator и IntoIterator определяют Item .

Итак Flatten , коллекция other IntoIterator ( O ) , являющаяся целью для доступа к этим внутренним элементам IntoIterator, должна Flatten::Item быть такой же, как и внутренняя IntoIterator::Item , следовательно:

type Item = <O::Item as IntoIterator>::Item;

Поскольку мы реализуем Iterator Self::Item этот элемент, определяемый реализацией (внутренние, которые мы только что объяснили).

В качестве резюме:

  • O::Item => Внутренний IntoIterator::Item для сглаживания
  • Self::Item => Сгладить как итератор Item . Который соответствует предыдущему.
  • Flatten::Item => То же, Self::Item что и для Iterator реализации.

Комментарии:

1. Спасибо за объяснение. Это помогло мне увидеть, что у меня была очевидная логическая лазейка в моем понимании синтаксиса.