I have an enum:
enum Expr {
Lit(u32),
Var(Id),
Ass(Id, u32),
Add(u32, u32),
Sub(u32, u32),
Mul(u32, u32),
}
I\'m tr
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),
}
}
}
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.
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.
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),
}
}
}
Both forms of matching are equivalent, but *self is more idiomatic and requires less typing :)