How to return the struct member as iter()

use std::collections::HashSet;
use std::iter::Chain;
use std::iter;
use std::iter::Once;

#[derive(Debug, Hash, PartialEq, Eq, Clone)]
pub struct Member{}

pub struct MyStruct {
    first: Member,
    others: HashSet<Member>,
}

impl MyStruct {

 pub fn iter(
        &self,
    ) -> Chain<Once<&Member>, std::collections::hash_set::Iter<&Member>> {
        iter::once(&self.first).chain(self.others.into_iter())
    }
}

How to make this compile?

std::collections::hash_set::Iter takes two generic parameters, the lifetime and the type so it should be std::collections::hash_set::Iter<'_, Member> (using lifetime elision) and you should use self.others.iter() not into_iter().

impl MyStruct {
    pub fn iter(&self) -> Chain<Once<&Member>, std::collections::hash_set::Iter<'_, Member>> {
        iter::once(&self.first).chain(self.others.iter())
    }
}

Moreover, you could use impl Trait to hide implementation details, I guess.

This makes the overall code a bit more readable, but impossible to store the iterator where you need to name the type.

use std::collections::HashSet;

#[derive(Debug, Hash, PartialEq, Eq, Clone)]
pub struct Member{}

pub struct MyStruct {
    first: Member,
    others: HashSet<Member>,
}

impl MyStruct {
    pub fn iter(
        &self,
    ) -> impl Iterator<Item = &'_ Member> {
        std::iter::once(&self.first).chain(self.others.iter())
    }
}

(Playground)

2 Likes

Thanks a lot, it works.

Note that it's a short form for:

    pub fn iter<'a>(
        &'a self,
    ) -> impl Iterator<Item = &'a Member> {
        std::iter::once(&self.first).chain(self.others.iter())
    }

You can also write it even more concise (see lifetime elision) like this:

    pub fn iter(
        &self,
    ) -> impl Iterator<Item = &Member> {
        std::iter::once(&self.first).chain(self.others.iter())
    }

(Playground)

You can further reduce to .chain(&self.others), thanks to the impl IntoIterator for &HashMap that is equivalent to its .iter().