I've got some code that attempts to run a match where each branch can return a different type, but all of these types implement Iterator<Item=usize>.
let found: Iterator<Item = usize> = match requirements {
Requirements::A => MatchingAs { ainternals: [] },
Requirements::B => MatchingBs { binternals: [] },
Requirements::C => MatchingCs { cinternals: [] },
};
return found.any(|m| m == 1)
... where MatchingAs, MatchingBs, and MatchingCs all impl std::iter::Iterator<Item = usize>.
I'm hitting a wall with the fact that the Iterator isn't sized:
| the trait `std::marker::Sized` is not implemented for `std::iter::Iterator<Item=usize>`
Is there a good approach to have match arms return objects with a shared trait, and then rely (only) on the trait in processing the results?
The first reflex when you want to return something that is not Sized, is to Box it (aka, put it on the heap, return a pointer):
let found: Box<Iterator<Item = usize>> = match requirements {
Requirements::A => Box::new(MatchingAs { ainternals: [] }),
Requirements::B => Box::new(MatchingBs { binternals: [] }),
Requirements::C => Box::new(MatchingCs { cinternals: [] }),
};
found.any(|m| m == 1)
This is not sufficient, here, because now match will complain that you return different types: Box<MatchingAs>, Box<MatchingBs>, ...
However, Box<Concrete> can be cast to Box<Trait> whenever there is an impl Trait for Concrete, so:
let found = match requirements {
Requirements::A => Box::new(MatchingAs { ainternals: [] }) as Box<Iterator<Item = usize>>,
Requirements::B => Box::new(MatchingBs { binternals: [] }) as Box<Iterator<Item = usize>>,
Requirements::C => Box::new(MatchingCs { cinternals: [] }) as Box<Iterator<Item = usize>>,
};
found.any(|m| m == 1)
There is, though, an allocation-less solution: use generics.
fn search<T: Iterator<Item = usize>>(t: T) -> bool {
t.any(|m| m == 1)
}
and then apply that function to each branch of the match:
match requirements {
Requirements::A => search(MatchingAs {ainternals: []}),
Requirements::B => search(MatchingBs {binternals: []}),
Requirements::C => search(MatchingCs {cinternals: []}),
}
The trade-off is that it's a bit closer to callback-hell, with a somewhat indirect flow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With