#rust
#Ржавчина
Вопрос:
Я пытаюсь реализовать лексер. Поскольку лексеры выделяют токены, я полагаю, что мы можем воспринимать лексер как специальный итератор, который сопоставляет определенные фрагменты char
s с Token
s . Поэтому я ожидаю Lexer
сохранить Iterator<Item=char>
и манипулировать этим итератором вместо a amp;str
, чтобы обеспечить максимальную гибкость.
struct Lexer<T: Iterator<Item=char>> {
source: T
}
Тем не менее, мне трудно манипулировать итератором, поскольку почти все адаптеры итераторов берут на себя ответственность, а с дженериками я не могу изменить тип T
во время выполнения, если не переключусь на Box
.
self.source.take_while(|x| x.is_whitespace())
Возможный обходной путь — потребовать, чтобы итератор реализовывал Clone
, использовал клон каждый раз, когда я хочу его преобразовать, запоминал, сколько символов я видел, и вызывал next
это много раз. Я считаю, что это слишком неуклюже.
Интересно, существует ли простой способ написания итераторов, которые сопоставляют неопределенное количество входных элементов (в данном случае, char
элементов) с другим объектом (в данном случае, Token
объектами)?
Самый элегантный способ, который я могу придумать до сих пор, — это использовать while let
etc. которые не так похожи на fluent-style. Я проверил реализацию GroupBy
in itertools
и обнаружил, что они тоже используют этот while let
подход.
Комментарии:
1.Вы можете использовать
.by_ref()
, чтобы не брать на себя ответственность за цепочки итераторов. например, игроваяself.source.by_ref().take_while(|x| x.is_whitespace())
площадка2. @kmdreko Спасибо! Я не знал, что итераторы также могут владеть изменяемыми ссылками. Теперь я знаю, как использовать
(amp;mut iter)
.3. Рад, что я смог помочь, это решает все ваши проблемы? Я не могу сказать, все ли это, что вам нужно, или у вас все еще есть проблемы с чем-то
4. @kmdreko Пока я не нашел никаких ошибок при его использовании. Еще раз спасибо! Я некоторое время балансировал ссылки при использовании итераторов, никогда не думал о добавлении одного самостоятельно 🙂