Hi! I've some questions concerning match patterns, I could not find the answers by googling, I hope they are not too stupid
So basically, to learn Rust I decided to write a (pseudo-) scheme interpreter and the core data structure is the Expr, so the idea was to have something like that (omitting a few variants for conciseness):
enum Expr {
Nil;
Integer(i64);
Cons(Expr, Expr);
}
Now obviously this doesn't work like that, the Expr
in Cons
must be a reference so the type can have a fixed size, I get that. I decided to use Rc for this, since a) a sub-expression can be referred by multiple expressions, so a Box would not be sufficient ; b) it's a toy project, no need to to worry about multithreading yet, so Rc
is enough.
So in my final version I have this:
enum Expr {
Nil;
Integer(i64);
Cons(Rc<Expr>, Rc<Expr>);
}
and it works, but I feel like I might be missing something with how match
works, because I end up having some ugly imbricated matches. E.g, when I want to check that the expression is a list of two elements and return them, I'd like to write something like this:
match expr {
Cons(x, Cons(y, Nil)) => (x,y),
_ => error()
}
Except, because of the Rc
(?) I didn't manage to get something like this working, and end up with something like that, which isn't as pretty:
match expr {
Expr::Cons(ref x, ref rest) =>
match **rest {
Expr::Cons(ref y, Expr::Nil) => (x.clone(), y.clone()),
_ => error()
},
_ => error()
}
So, time for my questions:
- why do I need to use namespace
Expr::
, and can I do something to get rid of those in match patterns toExpr
? I mean, when I match onOption
orResult
I don't need to qualify their namespaces, so it must be possible? - Is there a way to not have imbricated matches, even though the internal
Expr
is in aRc
? I tried putting some&
and*
in thematch
(a bit randomly in the end, I confess, I really don't have a clear model of howmatch
works for complicated cases) but could not get anything to work...