在一个枚举中如何匹配自我? [英] How to match over self in an enum?

查看:131
本文介绍了在一个枚举中如何匹配自我?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个枚举:

enum Expr {
    Lit(u32),
    Var(Id),
    Ass(Id, u32),
    Add(u32, u32),
    Sub(u32, u32),
    Mul(u32, u32),
}

我正在尝试实现一种方法:

I'm trying to implement a method:

impl Expr {
    fn eval(&self, env: &mut Env) -> Result<u32, String> {
        use Expr::*;

        match *self {
            Lit(l) => Ok(l),
            Var(id) => env.lookup(&id).ok_or_else(|| format!("undefined var {:?}", id)),
            Ass(id, v) => {
                env.assign(id, v);
                Ok(v)
            }
            Add(f, s) => Ok(f + s),
            Sub(f, s) => Ok(f - s),
            Mul(f, s) => Ok(f * s),
        }
    }
}

但是我收到以下错误:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:25:15
   |
25 |         match *self {
   |               ^^^^^ cannot move out of borrowed content
26 |             Lit(l) => Ok(l),
27 |             Var(id) => env.lookup(&id).ok_or_else(|| format!("undefined var {:?}", id)),
   |                 -- hint: to prevent move, use `ref id` or `ref mut id`
28 |             Ass(id, v) => {
   |                 -- ...and here (use `ref id` or `ref mut id`)

没有明星,我也得到一个错误:

Without the star, I'm also getting an error:

error[E0308]: mismatched types
  --> src/main.rs:25:17
   |
25 |                 Lit(l) => Ok(l),
   |                 ^^^^^^ expected &Expr, found enum `Expr`
   |
   = note: expected type `&Expr`
   = note:    found type `Expr`

我认为我理解第一个错误:我试图做的比我被允许的(不可变的)借用的 self ,但我是不确定第二个错误。我不知道如何正确地执行此操作。

I think I understand the first error: I'm trying to do more than I'm allowed with the (immutable) borrowed self, but I'm not really sure about the second error. I have no idea how to do this properly.

推荐答案

对于第一个问题,您需要使用 ref 关键字,如@Adrian所说:

For the first question, you need to use the ref keyword, as said by @Adrian:

impl Expr {
    fn eval(&self, env: &mut Env) -> Result<u32, String> {
        use Expr::*;

        match *self {
            Lit(l) => Ok(l),
            Var(ref id) => env.lookup(id).ok_or_else(|| format!("undefined var {:?}", id)),
            Ass(ref id, v) => {
                env.assign(id.clone(), v);
                Ok(v)
            }
            Add(f, s) => Ok(f + s),
            Sub(f, s) => Ok(f - s),
            Mul(f, s) => Ok(f * s),
        }
    }
}

使用 ref 可以防止模式匹配取得 id 的所有权。如你所说,你不能从 Expr 中获取 id 的值,因为你只有一个不可变的参考。 v f s 没有这个问题是因为它们是 u32 ,它实现 复制

Using ref prevents the pattern matching from taking ownership of id. As you mention, you are not allowed to take the value of id out of the Expr because you only have an immutable reference. v, f, and s don't have this problem because they are u32, which implements Copy. Instead of taking the value out, they are copied, leaving the original in place.

我不知道什么是 Env Id 类型是或 lookup 分配的定义,所以也许有些 clone()调用是没有必要的。

I don't know what the Env or Id type are, or the definitions of lookup and assign, so perhaps some clone() calls are not necessary.

对于你的第二个问题,是因为 self 的类型是& Expr ,所以你需要包括& / code>在模式中:

For your second question, this is because self is of type &Expr, so you need to include & in the patterns:

impl Expr {
    fn eval(&self, env: &mut Env) -> Result<u32, String> {
        use Expr::*;

        match self {
            &Lit(l) => Ok(l),
            &Var(ref id) => env.lookup(id).ok_or_else(|| format!("undefined var {:?}", id)),
            &Ass(ref id, v) => {
                env.assign(id.clone(), v);
                Ok(v)
            }
            &Add(f, s) => Ok(f + s),
            &Sub(f, s) => Ok(f - s),
            &Mul(f, s) => Ok(f * s),
        }
    }
}

两种形式的匹配都是等效的,但是 * self 更为惯用语,需要较少的输入:)

Both forms of matching are equivalent, but *self is more idiomatic and requires less typing :)

这篇关于在一个枚举中如何匹配自我?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆