Note: This question is obsolete since Rust 1.0. The
Iterator
trait now has an associated type,Item
, instead of a type parameter and a blanketIterator
implementation was added forBox<Iterator>
.
I want to define a trait method that returns an iterator. I want to avoid specifying what the actual return type is, so until we have unboxed abstract return types, I'm using trait objects. This means the method returns Box<Iterator<A>>
. But I'm not sure how to use a boxed trait object. I can't iterate over an object of type Box<Iterator<A>>
:
fn main() {
let xs = vec![0u, 1, 2, 3];
let boxed_iter = box xs.iter() as Box<Iterator<&uint>>;
for x in boxed_iter {}
}
This errors with "for" loop expression does not implement the "Iterator" trait
.
So my question is: How can I iterate over Box<Iterator<A>>
. Or, more generally, how can I used boxed trait objects?
collect() can take all the values in an Iterator 's stream and stick them into a Vec . And the map method is now generating Result<i32, &str> values, so everything lines up.
fn last(self) -> Option<Self::Item> Consumes the iterator, returning the last element. This method will evaluate the iterator until it returns None . While doing so, it keeps track of the current element. After None is returned, last() will then return the last element it saw.
Iterators can generally not be iterated twice because there might be a cost to their iteration. In the case of str::lines , each iteration needs to find the next end of line, which means scanning through the string, which has some cost.
In Rust, iterators are lazy, meaning they have no effect until you call methods that consume the iterator to use it up. For example, the code in Listing 13-10 creates an iterator over the items in the vector v1 by calling the iter method defined on Vec<T> . This code by itself doesn't do anything useful.
The issue is that Box<Iterator<A>>
does not itself implement the Iterator
trait. (I'm not sure exactly why, perhaps someone else can chime in on that point.)
You could remedy this yourself with:
impl<A> Iterator<A> for Box<Iterator<A>> {
fn next(&mut self) -> Option<A> { self.next() }
}
But since neither type nor trait are defined in your crate, this is not allowed. To work around this, you could define your own sub-trait of Iterator
, implement Iterator<A>
for all Box<MyIter<A>>
and then implement MyIter<A>
for all types I
that satisfy Iterator<A>
:
trait MyIter<A> : Iterator<A> {}
impl<A, I: Iterator<A>> MyIter<A> for I {}
// This is now allowed because `MyIter` is defined in this crate.
impl<A> Iterator<A> for Box<MyIter<A>> {
fn next(&mut self) -> Option<A> { self.next() }
}
And you'd have to change your code to use as Box<MyIter<&uint>>
:
fn main() {
let xs = vec![0u, 1, 2, 3];
let mut boxed_iter = box xs.iter() as Box<MyIter<&uint>>;
for x in boxed_iter { println!("{}", x); }
}
(I added mutability to boxed_iter
since it is required for iterators.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With