[Question]: Getting enum values

Hello!
I need to get the value of an enum. For some reason I can not do something like this:

enum Type {
    IntType {value: i32, start: Position, end: Position},
    FloatType {value: f32, start: Position, end: Position}
}
let x = Type::IntType {value: 10, start: start, end: end}
x.start
//^^^^^ Start will be in all variations of Type but it doesn't work.

I can not do:

match self {
    Type::IntType {value, start, end} => {start},
    Type::FloatType {value, start, end} => {start}
}

or the if let thing. I just want the value start. I hope there's a way to do this? If not, I think I can do something using traits and structs or whatever <T> is?

You must use a match (or if let). There's no way around it. Maybe a function would make your code clearer?

enum Type {
    IntType {value: i32, start: Position, end: Position},
    FloatType {value: f32, start: Position, end: Position}
}

impl Type {
    fn start(&self) -> Position {
        match self {
            Type::IntType { start, .. } => *start,
            Type::FloatType { start, .. } => *start,
        }
    }
}
1 Like

Unfortunately, using matches is disgusting:

    pub fn plus_op(&self, other: Type) -> RTResult {
        match self {
            Type::NullType {start: selfstart, end: selfend} => {
                let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: selfend.clone()}, value: Type::NullType {start: selfstart.clone(), end: selfend.clone()}};
                return res.failure(InterpreterException {
                    failed: true,
                    name  : "TypeError".to_string(),
                    msg   : "Null can not be added to".to_string(),
                    start : selfstart.clone(), end: selfend.clone()
                });
            },

            Type::IntType {value: selfvalue, start: selfstart, end: _} => {
                match other {
                    Type::IntType {value: othervalue, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.success(
                            Type::IntType{value: selfvalue + othervalue, start: selfstart.clone(), end: otherend}
                        );
                    },

                    Type::NullType {start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "Null can not be added to Int".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    },

                    Type::FloatType {value: _, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "Float can not be added to Int".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    },

                    Type::StringType {value: _, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "String can not be added to Int".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    }
                }
            },

            Type::FloatType {value: selfvalue, start: selfstart, end: _} => {
                match other {
                    Type::FloatType {value: othervalue, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.success(
                            Type::FloatType{value: selfvalue + othervalue, start: selfstart.clone(), end: otherend}
                        );
                    },

                    Type::NullType {start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "Null can not be added to Float".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    },

                    Type::IntType {value: _, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "Int can not be added to Float".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    },

                    Type::StringType {value: _, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "String can not be added to Float".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    }
                }
            },

            Type::StringType {value: selfvalue, start: selfstart, end: _} => {
                match other {
                    Type::StringType {value: othervalue, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.success(
                            Type::StringType{value: selfvalue.to_string() + othervalue.as_str(), start: selfstart.clone(), end: otherend}
                        );
                    },

                    Type::NullType {start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "Null can not be added to String".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    },

                    Type::IntType {value: _, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "Int can not be added to String".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    },

                    Type::FloatType {value: _, start: _, end: otherend} => {
                        let mut res = RTResult {exception: InterpreterException {failed: false, name: "".to_string(), msg: "".to_string(), start: selfstart.clone(), end: otherend.clone()}, value: Type::NullType {start: selfstart.clone(), end: otherend.clone()}};
                        return res.failure(InterpreterException {
                            failed: true,
                            name  : "TypeError".to_string(),
                            msg   : "Float can not be added to String".to_string(),
                            start : selfstart.clone(), end: otherend.clone()
                        });
                    }
                }
            }
        }
    }

Is it possible to get a value from an enum fallback? Something like:

match self {
    IntNode {start, end, value} => {/*dosomething*/},
    _ {start, end, ...} => {/*dosomething*/}
//     ^^^^^^^^^^^^^^^ Like this.
}

Which algebraic expression is simpler?

1. a*b*c + a*b*d
2. a*b*(c + d)

If you're evaluating an algebraic expression it can help to put it in minimal form. Structs and enums are called algebraic data types because you can do the same thing. Factor out the common stuff to another struct.

struct Type {
    value: Value,
    start: Position,
    end: Position,
}

enum Value {
    Int(i32),
    Float(f32),
}

impl Type {
    pub fn plus_op(&self, other: Type) -> RTResult {
        // use a tuple to match both at once so you don't need to nest `match`es
        match (self.value, other.value) {
            (Value::Int(this), Value::Int(that)) => { ... }
            (Value::Float(this), Value::Float(that)) => { ... }
            (v, w) => { /* error handling code */ }
        }
    }
}
5 Likes

That is so much simpler! Thank you.

Quick unrelated side-question: Is there a way to get the name of the enum variant?

enum Value {
    NullType,
//  ^^^^^^^^ Name of the enum variant `NullType`
    IntType(i32)
//  ^^^^^^^ Name of the enum variant `IntType`
}
let x = Value::IntType(10);
functionname(x); // Something like getVariantName(x);
x // Should return String or &str `IntType`

You will need a match for that too.

match value {
    Value::NullType => "NullType",
    Value::IntType(_) => "IntType",
}
1 Like

Well that's annoying. Thanks.

Rust is a compiled language, not one that is interpreted at runtime. Thus source artifacts are not generally available at execution time. However, Rust's meta-programming capabilities via macros make it easy to generate a match such as @alice did in her immediately-prior post.

1 Like

Yes. I realised that. Hard coming from Python. The following reply was a good work-around for me.