I think most people end up regretting code that users itertools::Either at the moment and use it reluctantly.
Ie, if I wanted an enum of either a string or an integer, it becomes "Either<&str, i64>".
But what I wanted is that it's either a string identifier or the database Id of something to be later referenced, which might be better described as "enum IdentOrDbId { Ident(String), DbId(i64) }".
This is of course a much simplified example of things I've faced.
fn some_func() -> impl SomeTrait {
if some_condition {
Either::Left(a)
} else {
Either::Right(b)
}
}
Both a and b will implement SomeTrait which is all callers care about. However, because they're structurally different they must be wrapped in an Either that delegates all methods from SomeTrait to a or b respectively.For object-safe traits where this would be possible, you can at least do this at the cost of an allocation, as you probably know:
fn some_func() -> Box<dyn SomeTrait> {
if some_condition {
Box::new(a)
} else {
Box::new(b)
}
}