Cloning a peekable chars iterator


#1

Hey, I’m writing a lexer where I’m using Peekable<Chars<'a>> to iterate over the input string. At some point in the code I noticed that I need to be able to peek more than once. So I tried to clone the iterator and try to iterate over the clone and avoid consuming the original, but then I got an error I didn’t understand.

let c = "".chars().peekable().cloned();

Gives the error

error[E0271]: type mismatch resolving `<std::iter::Peekable<std::str::Chars<'_>> as std::iter::Iterator>::Item == &_`
  --> <anon>:2:35
   |
 2 |     let c = "".chars().peekable().cloned();
   |                                   ^^^^^^ expected char, found reference
   |
   = note: expected type `char`
   = note:    found type `&_`

I read the error E0271 but it didn’t help me understand the problem. Can someone explain?
PS: I know I can use itertools to be able to peek multiple times ahead, which would solve my issue.


#2

You probably want clone, not cloned :slight_smile: The former clones the iterator itself while the latter returns an adaptor that clones items.


#3

Yeah, the error is hard to understand.

Instead of calling clone() you’ve called .cloned(), which changes what items are iterated. It’s defined as:

fn cloned(self) … where Self: Iterator<Item=&T>

So it’s for iterators that iterate references. The error message is trying to tell you that your iterator iterates char, not &char:

type mismatch resolving <yadayada as Iterator>::Item == &_

This says that for cloned() the Item of the Iterator is expected to be a reference & of something (anything) _. But for peekable chars iterator the item is char.


#4

You guys are right, thank you. I was looking at the page for the Iterator trait instead of Peekable, not wonder I didn’t find .clone().

I do have a followup question:
When I clone a Peekable<Chars<'a>>, I’m not cloning the whole string the original iterator is referencing? I assume it’s just getting another reference to the string that the Chars<'a> is holding.


#5

Cloning of references is shallow, just clones the reference itself, so for iterators it should be very cheap (just clones an index into the string).


#6

All right, thank you.