#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
, всегда aSelf::Item
,O::Item
или<O::Item as IntoIterator>::Item
. Никакой двусмысленности.2. Мне трудно понять этот вопрос, в частности, «Является
Item
ли inFlatten
все еще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. Спасибо за объяснение. Это помогло мне увидеть, что у меня была очевидная логическая лазейка в моем понимании синтаксиса.