如何处理从HashMap获得的值

moc*_*chi 2 rust

我希望我的getv()函数从a返回值HashMap.无论我如何修改代码,我都会收到错误:

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,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

use*_*342 5

HashMap::get返回一个Option<&Type>,而不是一个Option<Type>,这就是为什么只返回匹配的值无法编译.

get提供了一个引用,因为在Rust中你不能简单地返回哈希表中的实际值 - 你需要克隆它(制作副本,可能很昂贵),其从容器中删除并将其传输给调用者,或者返回一个引用里面的值.HashMap::get选择最后一个选项,因为它是便宜的,同时为调用者​​提供最大的灵活性,可以选择检查值或克隆它.

对于由单个机器字组成的枚举,复制该值将是最佳方法.(对于更复杂的枚举,更好的方法是返回参考,如Simon的回答所示.)复制需要:

  • Type通过Copy使用#[derive(Copy, Clone)]类型定义中的指令用特征标记它来制作可复制的.

  • getv通过使用*matched_value&在模式中使用取消引用匹配值来返回副本.

最后,您的getv方法使用对象,这意味着您只能调用一次.这几乎肯定不是预期的 - 它应该接受&self.通过这些更改,生成的代码如下所示:

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,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果类型需要包含非Copy数据,那么您只能Clone改为使用,然后返回v.clone().