Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the associated type `IntoIter` when implementing `IntoIterator` by using iterator composition in Rust?

I am currently trying to implement a structure of arrays. I want to implement the IntoIterator for the SOA in a way that yields the base structure on the fly, as if I was iterating over an array of structures. Here is the to types: the structure and its SOA,

struct Particle {
    x: f64,
    y: f64,
    v: [f64; 3]
}

struct ParticleSOA {
    x: Vec<f64>,
    y: Vec<f64>,
    v: Vec<[f64; 3]>,
}

By using the 'izip!' macro from itertools, It is quite easy to build an iterator by zipping the Vecs of my SOA and mapping the produced tuples to the original structure. However I can't find out what Type to give to the associated type IntoIterrequired for the IntoIterator trait.

impl IntoIterator for ParticleSOA{
    type Item = Particle;

    type IntoIter = ???;

    fn into_iter(self) -> Self::IntoIter {
       izip!(self.x,self.y,self.v).map(Particle::from)
    }
}

Is there a clever way to infer the type from my implementation of the into_iter function, Or my only choice is to work out the precise type created by the composition of iterator functions by hand?

EDIT

The secret was getting rid of closures, especially the one hidden in izip! Itertools has a multizip function that produces a usable type.

impl IntoIterator for ParticleSOA {
    type Item = Particle;

    fn into_iter(self) -> Self::IntoIter {
        multizip((self.x, self.y, self.v)).map(Particle::from)
    }

    type IntoIter = Map<
        itertools::Zip<(
            std::vec::IntoIter<f64>,
            std::vec::IntoIter<f64>,
            std::vec::IntoIter<[f64; 3]>,
        )>,
        fn((f64, f64, [f64; 3])) -> Particle,
    >;
}

Note : My struct conveniently implements From<(f64, f64, [f64; 3])>.

like image 282
Quettle Avatar asked Mar 11 '26 01:03

Quettle


1 Answers

Adding to what @Netwave said, with the unstable feature type_alias_impl_trait you can specify impl Iterator in an associated type:

#![feature(type_alias_impl_trait)]

impl IntoIterator for ParticleSOA {
    type Item = Particle;

    type IntoIter = impl Iterator<Item = Particle>;

    fn into_iter(self) -> Self::IntoIter {
       izip!(self.x,self.y,self.v).map(Particle::from)
    }
}

Playground.

like image 133
Chayim Friedman Avatar answered Mar 13 '26 15:03

Chayim Friedman