How to iterate over non-generic enum data variants

This is a simple example of the enum I want to be able to iterate on:

pub enum FloatVec {
    F32(Vec<f32>),
    F64(Vec<f64>),
}

I have the feeling this should have a simple solution but I'm struggling a lot with this problem. Since I'm not using generic types I'm lost in regards to what to use as an associated type, for instance.

iterator can only have a single return type so you cant have an iterator that either returns f32 or f64 but you can have a single type which is f32 or f64

pub enum Float{
    F32(f32),
    F64(f64),
}
1 Like

You could

  • Return an enum that could be f32 or f64 like @Mokuz suggested
  • If this is about iterating over values and not references specifically:
    • Always return an f64
    • Always return an f32 but lose precision
  • Don't implement Iterator/IntoIterator on the enum as a whole, and instead iterate on whichever the underlying Vec is
    • You may find yourself using generics or macros to cut down on code duplication with this approach
1 Like

thank you both for your fresh ideas, I'm gonna have to ponder on this some more.

So if my real enum has about 20 types then I'd have to return an enum with 20 variants and figure out ways to reduce that complexity, maybe with a bunch of impl Into<...>.

@quinedot the second proposal is not an option for me, since not all the values are able to be coerced.

Do you have a simple example of how your last proposal of iterating on the underlying vec would be? I'm not sure I'm visualizing it right. Do you think that'd be feasible if my real enum has more levels of nesting?

This would be the parent level of the enum to iterate on, but there are more levels:

pub enum Numerical {
    Int(IntVec),
    Float(FloatVec),
}
pub enum IntVec {
    I8(Vec<i8>),
    U8(Vec<u8>),
    I16(Vec<i16>),
    // ...
}

(This won't be practical for your 20 variants, but we were racing in our replies...)

Another alternative to iteration is to turn it inside out and have consumers of FloatVec supply the body of the loops as closures (one for f32s and another for f64s).

Example.

I like very much your example using closures, it's very interesting! but you're right that's not gonna fly in my case, because of the number of variants and I also have vecs of strings, and other types...

So in my mind the 20 variant enum return type solution is the most promising. The other option I'm considering would be to refactor everything with generics but that would probably mean a different set of problems... And I was very happy with the system until I had to tackle iterators...

I just meant something like this where you branch on the underlying type before looping, so you have one loop per variant (instead of branching each iteration inside one loop).

I've done similar things and it does lead to a lot of repetition and boiler plate, which you can reduce somewhat with generics and/or macros.

1 Like

Oh I see. Yes I like that.

Now I just made the function a method, and a single constructor that can accept a vec directly, and I really like where this is going (updated example),

I also like this can work alongside the other solution of returning an enum. Which also has a lot of potential...

Thank you both for your invaluable assistance.

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.