Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I have a struct's field be an `Iterator` over `T` elements?

Tags:

rust

I want a struct's field to be an Iterator over T elements, however Iterator doesn't have a type parameter. I know I'm trying to do something fundamentally wrong, what though?

like image 388
Yuri Geinish Avatar asked Dec 15 '17 19:12

Yuri Geinish


1 Answers

In Rust, Iterator (more specifically Iterator<Item = T> where T is the type yielded when iterating) is a trait. Types that represent iterators implement this trait.

This is an instance of the more general question "how can I store a value of a trait in a struct?". I deliberately phrased the question in an imprecise way -- what we actually want is to store a value of a type implementing the trait, and there are broadly two ways to do that.

Put it in a box

The easiest way is to use a Box<Iterator<Item = T>>. The Box represents an owned pointer, and when you have a pointer to a trait object, Rust creates a "fat pointer" including runtime information about the type. This way the concrete type of the iterator is not known at compile time.

The definition looks like this:

struct IteratorHolder {
    iter: Box<Iterator<Item = u32>>,
}

And usage:

let ih = IteratorHolder { iter: Box::new(0..10) };
println!("{:?}", ih.iter.collect::<Vec<_>>());

Generics

Another way to do the same thing, while avoiding allocating any boxes on the heap, is to use a generic struct. This way we will have some type implementing Iterator<Item = T>, and what it is concretely will be determined at compile time.

Definition:

struct IteratorHolder<I: Iterator<Item = u32>> {
    iter: I,
}

And usage:

let ih = IteratorHolder { iter: 0..10 };
println!("{:?}", ih.iter.collect::<Vec<_>>());
like image 165
durka42 Avatar answered Oct 17 '22 21:10

durka42