Extracting value from an enum

I'm using the following enum to build lists of similar items.

pub enum TypeWrapper {
    Alphanum(String),
    Unsigned(u64),
    Integer(i64),
    Floating(f64),
    Letter(char),
}

I define a vector using the TypeWrapper type like this:

let mut newlist: Vec<TypeWrapper> = Vec::new();

If I want a list of Strings, I fill the vector with strings. Then the list would look like this when printed:

[Alphanum("bantam"), Alphanum("rhode island reds"), Alphanum("leghorns")]

In order to be useful, however, I need to extract the values from the enums. After doing that the list vector would look like this:

["bantam", "rhode island reds", "leghorns"]

I did this once before, but for the life of me, I can't reproduce it again. So, how do I go about extracting the values from the enums?

Thanks!

You can do something like this to extract the String when it exists...

impl TypeWrapper {
    fn into_string(self) -> Option<String> {
        match self {
            Self::Alphanum(s) => Some(s),
            _ => None,
        }
    }
}

...and then use it to rebuild the Vec<TypeWrapper> into a Vec<String>...

fn example(v: Vec<TypeWrapper>) {
    let _: Vec<String> = v
        .into_iter()
        .filter_map(TypeWrapper::into_string)
        .collect();
}

...or maybe you really wanted something like this, I'm not sure.

pub enum TypeWrapper {
    Alphanum(Vec<String>),
    Unsigned(Vec<u64>),
    Integer(Vec<i64>),
    Floating(Vec<f64>),
    Letter(Vec<char>),
}
6 Likes

I'm new to Rust, but had a similar situation and ended up liking std::fmt::Display for this scenario. Maybe it will help you as well.

impl fmt::Display for TypeWrapper {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            TypeWrapper::Alphanum(val) => write!(f, "{}", val),
            // ...
        }
    }
} 

Then you could do something like:

fn main() {
    let alphanums: Vec<TypeWrapper> = vec![
        TypeWrapper::Alphanum("apples".to_string()),
        TypeWrapper::Alphanum("yeehaw".to_string()),
    ];
    
    let converted_alphanums: Vec<String> = alphanums
        .iter()
        .map(|an| an.to_string())
        .collect();
    
    println!("{:?}", converted_alphanums); // yields ["apples", "yeehaw"]
}

You are (ab)using the Display trait. You shouldn't do that, traits have names to be semantically relevant; the Display trait should be used solely for the purpose of printing the value to stdout. I would have a dedicated implementation of the ToString trait in that case, although that would still fall into the case of trait abuse.

A simple method to extract the strings would be more succint.

Seems I have some refactoring to do, then, ha.

Here's my corrected proposed solution for this thread's initial problem, then:

impl string::ToString for TypeWrapper {
    fn to_string(&self) -> String {
        match self {
            TypeWrapper::Alphanum(val) => val.to_string(),
        }
    }
} 

The main should remain the same as above.

1 Like
#[derive(Debug)]
enum TypeWrapper {
    Alphanum(String),
    Unsigned(u64),
    Integer(i64),
    Floating(f64),
    Letter(char),
}

impl From<&str> for TypeWrapper {
    fn from(value: &str) -> Self {
        Self::Alphanum(value.to_owned())
    }
}

impl From<u64> for TypeWrapper {
    fn from(value: u64) -> Self {
        Self::Unsigned(value)
    }
}

impl From<i64> for TypeWrapper {
    fn from(value: i64) -> Self {
        Self::Integer(value)
    }
}

impl From<f64> for TypeWrapper {
    fn from(value: f64) -> Self {
        Self::Floating(value)
    }
}

impl From<char> for TypeWrapper {
    fn from(value: char) -> Self {
        Self::Letter(value)
    }
}

pub fn extracting_value_from_an_enum() {
    let new_list = vec![
        TypeWrapper::from("StringValue"),
        TypeWrapper::from(64_u64),
        TypeWrapper::from(64_i64),
        TypeWrapper::from(64.0),
        TypeWrapper::from('A'),
    ];

    println!("list items are: {:?}", new_list);
}

output:

list items are: [Alphanum("StringValue"), Unsigned(64), Integer(64), Floating(64.0), Letter('A')]

Is this AI-generated code? Just so you know, posting AI-generated code is not allowed here, because it's... inaccurate (for the lack of a better euphemism).

@yosimcy I'd love to hear your reply to @moy2010 since the code definitely didn't work. I think it's an interesting approach to the problem, but I'm not sure I see a way to make it work correctly. I'd love to discuss it with you more.

I like your solution. I've been playing around with it this morning and it's pushing me in my skills. This is a good thing, BTW :>). It means I'm learning something. For instance, closures are kind of a mystery to me, but using one in the map() method is forcing me to use one. Deciphering your impl block took me a bit, but I think I have a decent handle on it now. Anyway, everything works fine. Now to get it working with the other enum variants. I'll come back with any questions.

Thanks for your help!

1 Like

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.