Impl iterator on newtype-wrapped vec


#1

Hello,

I was wondering if it was crazy to implement iterator on a struct newtype wrapping a vec.

pub struct AgencyList(Vec<Agency>);

So far, with what I have, I can have a struct method return the iterator from the vec easily enough. But I thought it might be useful to implement the Iterator trait so that a user could directly call

let agencies = Agencylist::new(vec![Agency1, Agency2]);
for agency in agencies {
...
}

instead of having to call

for agency in agencies.iter()

It did cross my mind that having to do this kind of mucking around could be an anti-pattern (i.e. why use the wrapper at all?). My reasons are mostly for consistency of API throughout the program.


#2

What you want is IntoIterator. The iterator given to for is always passed through that, which is why you can do for e in vec![...] { ... }; Vec doesn’t implement Iterator.


#3

There is an interesting pattern of iterating over a Vec with &, which was like “Wow, super cool” when I learned it. Do you know this:

fn main() {
    let xs = vec![String::from("hello"), String::from("world")];

    for s in &xs {
        // s is a ref
    }

    for s in xs.iter() {
        // the same as above, but less idiomatic
    }

    for s in xs {
        // s is moved out of the vec
    }

    // no xs here
}

This is called collections are smart pointers idiom, and I think it may be applicable in your case.


#4

This actually works because &Vec<T> implements IntoIterator.


#5

Thanks, I was mistaken about how it works!

Am I correct that even if &Vec<T> didn’t implement IntoIter, then for s in &xs would still work the same because Vec<T> implements Deref<Target=[T]>?


#6

No, it would not, we do not perform automatic dereferences in for.


#7

for behaves like an ordinary generic function call (IntoIterator::into_iter(&xs)). We don’t autoderef because we don’t key normal deref coercions on obligations.


#8

Thanks, this completely answered the question! The example on this page was great too, and learned about this syntax for accessing fields in tuple structs:

struct AgencyList(Vec<Agency>);

let agencies = Agency::new();
let agencies_inner = agencies.0;

#9

This is really cool! I’m going to dig into this, really enjoying the power of Rust’s type system.

Also, the repo you pointed to is great, I’d like to read more about design patterns and idiomatic usage. As far as I can tell, info on this stuff is relatively scattered and sparse right now. (Or at least it wasn’t easy for me to find).