How to create the same type of enum variable with union?


#1

Hi, so I have an enum defined as follows:

enum MyTest{
   Test1(i32),
   Test2(i32),
   ...
   Test11(i32,i32),
   ....
   Test21(Vec<i32>)
}

What I want is to be able to create the same variable type, but with different value. currently I only have figured out to do exhaustive match:

fn recreate(&self, val: i32) {
   match *self{
      MyTest::Test1(_) => MyTest::Test1(val),
      ....
      MyTest::Test10(_) => MyTest::Test10(val),
      _ => panic!()
   }
}

Is there any more generic way than writing this?
E.g. something where in the match I can do MyTest::Test1(_) | MyTest::Test2(_) | ... | MyTest::Test10(_) and have it as a one line the return statement.

EDIT: I’ve edited the question with some extra info because I posed it in a confusing way, discarding that I have enums with more than 1 attached variable.


#2

How about this?:

enum MyTestType {
    Test1,
    Test2,
    ...
    Test22,
}

struct MyTest { type: MyTestType, val: i32 }

impl MyTest {
    fn recreate(&self, val: i32) {
        MyTest { type: self.type, val: val }
    }
}

#3

That was the suggestion I was about to make. Except type is a reserved keyword, which is quite infortunate :(.


#4

Yeah, this was my second option to just make to a struct. The reason being it is not a struct is that in fact the enums have different number of variables attached, and some even have Vec<i32>. Sorry, for that should have explain it in the question. And well since I want to enforce the number of i32 and currently Rust does not support const int as template arguments I decided to stick to enums. Anyway, I guess for now thats the only option.


#5

I don’t quite understand what you’re trying to do. So you have something like this and you’re trying to map it to i32?

enum MyTest{
   Test1(i32, Vec<i32>),
   Test2(Vec<i32>, u32, String),
   ....
   Test22(i32)
}

[EDIT]:

Oh, I get it.


#6

I edited the question, sorry for the initial confusion.


#7

This is still too vague: when you have two i32, do you want to replace the first? the second? both? And what of the vector case: replace the first? all? replace by a vector with a single element?

Obviously, you must write code for each possible behaviour, there is no way around it. Apart from that, you should devise your data structure in a way that makes independent parameters separate.

But more basically, the question is: WHY?


#8

So I want to map only the values with single value, why … well its more of a question of the type ‘Is this possible to be done’ (e.g. I’m experimenting with stuff in Rust and learning it along the way), rather than ‘This is my optimal way to do it’


#9

I very much doubt it can be done directly like that. You should design your data structure for proper orthogonality: if there is a value that you want to act upon, it must be isolated:

enum Subtest {
    Test3a,
    Test3b,
    Test3c(Vec <i32>),
    ...
}
enum Test {
    Test1(i32, Vec <i32>),
    Test2(Vec <i32>, u32, String),
    Test3(i32, Subtest),
}

That way, you only have to match Test3.