2

I need to take two Vecs of different concrete types and process each combination of list A and B. I can see two ways to do it:

  1. enum * enum

    Wrap the concrete type in an enum, use match, use generic functions in trait signatures.

  2. dyn * dyn

    Use trait objects, and never use generic functions in the trait signatures.

Are there any other ways do to this?

My aim is a nested loop where the concrete types of each loop can be different types implementing the same trait, or something semantically equal.

struct S1 {}
struct S2 {}

struct SA {}
struct SB {}

trait TTakerConcrete {
    fn do_action_concrete<T: TGiver>(&self, g: &T) {
        // Do some custom processing per struct
        g.give_data();
    }
}

trait TTakerDyn {
    fn do_action_dyn(&self, g: &dyn TGiver) {
        // Do some custom processing per struct
        g.give_data();
    }
}

trait TGiver {
    fn give_data(&self) -> String {
        "diff string per struct".to_string()
    }
}

// Nums are takers.
impl TTakerDyn for &S1 {}
impl TTakerDyn for &S2 {}
impl TTakerConcrete for &S1 {}
impl TTakerConcrete for &S2 {}
impl TTakerDyn for S1 {}
impl TTakerDyn for S2 {}
impl TTakerConcrete for S1 {}
impl TTakerConcrete for S2 {}

// Letters are givers.
impl TGiver for &SA {}
impl TGiver for &SB {}
impl TGiver for SA {}
impl TGiver for SB {}

fn dyn_dyn(t: Vec<&dyn TTakerDyn>, g: Vec<&dyn TGiver>) {
    for n in t {
        for l in &g {
            n.do_action_dyn(*l);
        }
    }
}

fn enum_enum(t: Vec<&Nums>, g: Vec<&Letters>) {
    for n in t {
        for l in &g {
            match n {
                Nums::S1(s1) => match l {
                    Letters::SA(sa) => s1.do_action_concrete(sa),
                    Letters::SB(sb) => s1.do_action_concrete(sb),
                },
                Nums::S2(s2) => match l {
                    Letters::SA(sa) => s2.do_action_concrete(sa),
                    Letters::SB(sb) => s2.do_action_concrete(sb),
                },
            };
        }
    }
}

enum Nums {
    S1(S1),
    S2(S2),
}
enum Letters {
    SA(SA),
    SB(SB),
}

fn main() {}

playground

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
zino
  • 1,222
  • 2
  • 17
  • 47
  • from my point of view it's quite hard to understand it. – Stargateur Nov 11 '20 at 14:55
  • 1
    I would advice to always prefer enum, unless you have a very strong reason to not to. – Stargateur Nov 11 '20 at 14:56
  • 1
    See also [Should I use enums or boxed trait objects to emulate polymorphism?](https://stackoverflow.com/q/52240099/155423) – Shepmaster Nov 11 '20 at 14:58
  • 1
    My opinion is to use enums. That way you can statically verify all combinations are accounted for. – Shepmaster Nov 11 '20 at 15:00
  • How about something like `fn impl_impl(t: Vec<&impl TTakerDyn>, g: Vec<&impl TGiver>)`. – Mihir Luthra Nov 11 '20 at 15:06
  • 1
    @Mihir this compiles, but I do not think it would allow a `Vec` of different concrete structs (in your example the concrete types must all be the same for a single `Vec`). – zino Nov 11 '20 at 15:10
  • @Shepmaster - what needs to change in order to have this question be "fact based" and avoid closing it as opinion? – zino Nov 12 '20 at 18:07
  • 2
    This question is not asking "Which is better, enum or dyn", which would be an opinion. It's asking for the pros and cons of each, which are factual. – Andy Lester Nov 12 '20 at 18:27
  • Part of the issue is that it's quite difficult to explain the question in a single title. I think listing "code alternatives" is not opinion based, but the rationale for choosing one option over another may be construed as opinion based. Given the same compiler, CPU and input data, the performance of the code should be close to deterministic (as opposed to a JIT which is more of a black box). Running inputs through a set of different programs to compute an output and asking how they differ does not seem like an opinion at all. – zino Nov 12 '20 at 19:06
  • 1
    @zino I didn't mark this as opinion based, that is shown because it was the plurality of the vote. I voted to close it as "Needs more focus — This question currently **includes multiple questions** in one. It should focus on one problem only". – Shepmaster Nov 12 '20 at 19:13
  • 1
    The answer to the current question is "No". – Shepmaster Nov 12 '20 at 19:14
  • ok, thanks I appreciate the help – zino Nov 12 '20 at 20:31

0 Answers0