Printing each struct within a struct on a newline

I am trying to implement a display_snakes() function that will print every Snake within a SnakePool struct. Issue is that SnakePool nor Snake can implement Copy, and Iterator is not implemented for SnakePool. I have tried implementing Copy on both, and Iterator on SnakePool but am not clear on exactly how to do it correctly. I do not want the display_snakes() function to consume the SnakePool struct or the Snakes within.

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Point {
    pub latitude: Latitude,
    pub longitude: Longitude,
}
impl Point {
    pub fn new() -> Self {
        let mut rng = rand::thread_rng();
        Self {
            latitude: Latitude::new(&mut rng),
            longitude: Longitude::new(&mut rng)
        }
    }
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Snake {
    id: Option<u32>,
    point: Point,
    body: Vec<Point>,
    collapse: bool,
}
impl Snake {
    pub fn new(id: u32) -> Self {
        Self { id: Some(id), point: Point::new(), body: vec![], collapse: false }
    }
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SnakePool {
    snakes: Vec<Snake>
}
impl SnakePool {
    pub fn new() -> Self {
        Self {
            snakes: {
                let mut snakes = Vec::new();
                for n in 0..10 {
                    let snake = Snake::new(n);
                    snakes.push(snake);
                }
                snakes
            }
        }
    }
    pub fn display_snakes(self) {
        for snake in self {
            println!("Snake: {:?}", snake)
        }
    }
}
fn main() {
    let snake_pool = SnakePool::new();
    snake_pool.display_snakes();
}

Error Code:

error[E0277]: `&SnakePool` is not an iterator
  --> src\snake_pool.rs:23:22
   |
23 |         for snake in self {
   |                      ^^^^ `&SnakePool` is not an iterator
   |
   = help: the trait `Iterator` is not implemented for `&SnakePool`
   = note: required for `&SnakePool` to implement `IntoIterator`

I'm not sure if you thought Rust would guess you were talking about the snakes fields by using for snake or not, but it won't.

You can use either of these to iterate over the contents of the Vec without taking ownership:

-        for snake in self {
+        for snake in self.snakes.iter() {
+//  or  for snake in &self.snakes {
2 Likes

Thank you for that. I was under the assumption that it would make the association. This being an artifact thought of using Python.
What exactly is the difference between,

for snake in self.snakes.iter() {}
for snake in &self.snakes {}

or is there none?

Neither consume self or self.snakes. They are effectively the same.

iter is a method on Vec. The &self receiver means it does not take ownership (consume) the Vec, it only borrows it.

The other alternative works because &Vec<_> implements IntoIterator. And in that method -- <&Vec<_> as IntoIterator>::into_iter -- the type of self is &Vec, so once again it is not taking ownership, you're just operating on the borrow.

(Vec also implements IntoIterator, but that would take ownership, and that's why you need the & in for snake in &self.snakes.)

They both work with for because for utilizes IntoIterator (and everything that implements Iterator also implements IntoIterator by returning itself).

1 Like

Thank you for helping me understand this better!

A while ago, I posted some examples regarding .iter() here.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.