Reputation: 5407
Situation:
I have a situation where I would like to call some method defined on the Iterator
trait on a function parameter. The function that I would like to call it is taking a parameter of a type which is a trait
called VecLike
. The function is called get_all_matching_rules
.
get_all_matching_rules
can receive either a Vec
or another similar home made type which also implements Iterator
. Of course both of these implement VecLike
. I was thinking of adding a function on VecLike
to have it return an Iterator
so that I could use it in get_all_matching_rules
.
If my parameter is named: matching_rules
I could then do matching_rules.iter().filter(
.
Question:
How do I return a non consuming iterator from a Vec
?
I'd like to be able to return a non consuming iterator on a Vec<T>
of type Iterator<T>
. I am not looking to iterate the items by calling .iter()
.
If I have (where self is a Vec):
fn iter<'a>(&'a self) -> Iterator<T> {
self.iter()
}
I get the following error:
error: mismatched types: expected `core::iter::Iterator<T>+'a`, found `core::slice::Items<'_,T>` (expected trait core::iter::Iterator, found struct core::slice::Items)
I would like to return the Iterator<t>
. If there is a better way to go at this rather than returning an Iterator
, I'm all ears.
Upvotes: 8
Views: 12032
Reputation: 90712
.iter()
on [T]
, which Vec<T>
automatically dereferences to, takes self by reference and produces a type implementing Iterator<&T>
. Note that the return type is not Iterator<&T>
; Iterator
is a trait which is implemented by concrete types, and the concrete type Items<T>
is the return type in that case, not Iterator<&T>
. There is not currently any syntax for specifying a return type merely as a trait that is implemented by it, though the syntax impl Iterator<&T>
has been suggested.
Now you wish something implementing Iterator<T>
rather than Iterator<&T>
. Under Rust’s memory model where each object is owned by exactly one thing, this is not possible with the same objects; there must be some constraint to allow you to get a new T
from the &T
. There are two readily provided solutions for this:
The Copy
trait, for types that can just be copied bitwise. Given a variable of a type implementing Iterator<&T>
where T
is Copy
, this can be written .map(|&x| x)
or .map(|x| *x)
(the two are equivalent).
The Clone
trait, for any types where the operation can be caused to make sense, regardless of Copy
bounds. Given a variable of a type implementing Iterator<&T>
where T
is Clone
, this can be written .map(|x| x.clone())
.
Thus, given a vector v
, v.iter().map(|x| x.clone())
. Generically, something like this:
fn iter<T: Clone>(slice: &[T]) -> Map<&T, T, Items<T>> {
slice.iter().map(|x| x.clone())
}
Upvotes: 9
Reputation: 16188
I'm not sure what you're asking here.
.iter()
creates an iterator (Items
) which does not move the Vec
(You'll get an Iterator over &T
).
Filter
(and most other iterator adapters) are lazy. Perhaps you should chain()
the two iterators before filtering them?
Otherwise, if you don't want the Filter
to be consumed, clone it.
Upvotes: 0