Reputation: 3558
I am trying to write a parser that passes an iterator over a vector to a function. The code is similar to this:
fn foo(itr : ???) {
while let Some(c) = itr.next() {
if *c != 0 {
break;
}
println!("{}", *c);
}
}
fn main() {
let v = vec![0; 10];
let itr = v.iter();
while let Some(c) = itr.next() {
foo(itr);
}
}
I am not sure how to write the type of the iterator over the vector. I tried putting the wrong type u32
to see what type rustc
expected: core::slice::Iter<'_, _>
. When I try to use core::slice
rustc complains Use of undeclared type or module 'core::slice'
Upvotes: 0
Views: 164
Reputation: 65802
There are many types of iterators; most of the time, what you really want is a function that is able to consume any of them. To do this, the idiomatic solution is to use generics.
fn foo<'a, T: Iterator<Item=&'a i32>>(mut itr: T) {
while let Some(c) = itr.next() {
if *c != 0 {
break;
}
println!("{}", *c);
}
}
fn main() {
let v = vec![0; 10];
let mut itr = v.iter();
while let Some(c) = itr.next() {
foo(itr);
}
}
The code above doesn't compile though, since it moves itr
into foo
, then tries to use it again on the while let
. To solve this, we need to pass the iterator by reference instead.
fn foo<'a, T: Iterator<Item=&'a i32>>(itr: &mut T) {
while let Some(c) = itr.next() {
if *c != 0 {
break;
}
println!("{}", *c);
}
}
fn main() {
let v = vec![0; 10];
let mut itr = v.iter();
while let Some(c) = itr.next() {
foo(&mut itr);
}
}
Instead of generics, we can also use a trait object:
fn foo<'a>(itr: &mut Iterator<Item=&'a i32>) {
while let Some(c) = itr.next() {
if *c != 0 {
break;
}
println!("{}", *c);
}
}
fn main() {
let v = vec![0; 10];
let mut itr = v.iter();
while let Some(c) = itr.next() {
foo(&mut itr);
}
}
The chapter on trait objects from the Rust book explains the difference between these solutions.
Upvotes: 3
Reputation: 3558
The solution was to add
use std::slice::Iter;
and the type was
fun foo<'a>(itr : &mut Iter<'a, i32>) {}
Upvotes: 0