How to return a Filter iterator


#1

At the moment I have a function with a signature: pub fn lex(r: &mut io::Read) -> Vec<Lexeme>, in this function I use Vec::from_iter(an_iterator.filter_map(|x| x)) and I would like to get rid of the vector-generating step, so that I can work lazily on this list. From Returning Iterators I figured that I should write something like this:

pub fn lex<I: Iterator<Item = Lexeme>>(r: &mut io::Read) -> I

Unfortunately this doesn’t work, and I don’t know how to make it work

error[E0308]: mismatched types
  --> src/lib/lib.rs:42:5
   |
42 |     r.chars()
   |     ^ expected type parameter, found struct `std::iter::FilterMap`
   |
   = note: expected type `I`
              found type `std::iter::FilterMap<std::iter::Map<std::io::Chars<&mut std:
:io::Read>, [closure@src/lib/lib.rs:43:14: 67:10 lineno:_, col:_]>, [closure@src/lib/l
ib.rs:68:21: 68:26]>`

EDIT: Having thought about it a little longer, I guess I have to implement my own iterator, not only for type-system reasons, but also for tracking the state of the iteration.


#2

On stable Rust, you can use dynamic dispatch to return a boxed Iterator:

foo<'a>(_: &'a _) -> Box<Iterator<Item = &'a _> + 'a>

On nightly, you can use static dispatch:

foo<'a>(_: &'a _) -> impl Iterator<Item = &'a _>
```
If you look it  up, I'm sure you'll find more detailed answers.

#3

You can also consider using internal iteration: make caller pass a closure that will be invoked on each element, rather than returning an iterator. Don’t know if that works in your particular example, but something to consider.


#4

Is this RFC 1522?


#5

Yes.