The*_*ler 13 enums pattern-matching rust
我有一个枚举:
enum Expr {
Lit(u32),
Var(Id),
Ass(Id, u32),
Add(u32, u32),
Sub(u32, u32),
Mul(u32, u32),
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试实现一个方法:
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),
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
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`)
Run Code Online (Sandbox Code Playgroud)
没有明星,我也会收到一个错误:
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`
Run Code Online (Sandbox Code Playgroud)
我想我理解了第一个错误:我试图做的不仅仅是我允许使用(不可变)借用self,但我不确定第二个错误.我不知道如何正确地做到这一点.
ant*_*oyo 14
对于第一个问题,您需要使用ref@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),
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用ref可防止模式匹配获得所有权id.至于你提到,你是不是允许采取的价值id出来的Expr,因为你只能有一个不变的参考.v,f并且s没有这个问题,因为它们是u32实现的Copy.它们不是取出价值,而是复制,留下原件.
我不知道什么Env或Id类型的,或者的定义lookup和assign,因此,或许一些clone()调用是没有必要的.
对于你的第二个问题,这是因为self是类型&Expr,所以你需要包含&在模式中:
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),
}
}
}
Run Code Online (Sandbox Code Playgroud)
两种形式的匹配都是等价的,但*self更惯用,需要更少的输入:)