I want my getv()
function return the value from a HashMap
. I get errors no matter how I modify my code:
enum Type {
TyInt,
TyBool,
}
struct TypeEnv {
Env: HashMap<char, Type>,
}
impl TypeEnv {
fn set(&mut self, name: char, ty: Type) {
self.Env.insert(name, ty);
}
fn getv(self, name: char) -> Type {
match self.Env.get(&name) {
Some(Type) => Type, // <------- Always error here
None => Type::TyInt,
}
}
}
HashMap::get
returns an Option<&Type>
, not an Option<Type>
, which is why just returning the matched value fails to compile.
get
provides a reference because in Rust you cannot simply return the actual value that is in the hash table - you need to either clone it (make a copy, potentially expensive), remove it from the container and transfer it to the caller, or return a reference to the value inside. HashMap::get
chooses the last option because it is cheap while providing the greatest flexibility to the caller, which can choose to either inspect the value or clone it.
For your enum that consists of a single machine word, copying the value would be the optimal approach. (For more complex enums, a better approach is to return a reference as shown in Simon's answer.) Copying requires:
making Type
copyable, by marking it with the Copy
trait using the #[derive(Copy, Clone)]
directive at the type definition.
returning the copy from getv
by dereferencing the matched value using *matched_value
, or by using &
in the pattern.
Finally, your getv
method consumes the object, which means that you can call it only once. This is almost certainly not what was intended - it should accept &self
instead. With those changes, the resulting code looks like this:
use std::collections::HashMap;
#[derive(Copy, Clone)]
enum Type {
TyInt,
TyBool,
}
struct TypeEnv {
env: HashMap<char, Type>,
}
impl TypeEnv {
fn set(&mut self, name: char, ty: Type) {
self.env.insert(name, ty);
}
fn getv(&self, name: char) -> Type {
match self.env.get(&name) {
Some(&v) => v,
None => Type::TyInt,
}
}
}
If the type needs to contain non-Copy
data, then you can make it only Clone
instead, and return v.clone()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With