[英]Matching a rust Enum with recursive definition using Rc
以下是我的测试代码。
use std::rc::Rc;
enum Node {
Cons(i32, Rc<Node>),
Nil,
}
fn main() {
let list = Rc::new(Node::Cons(1, Rc::new(Node::Nil)));
match &*list {
Node::Cons(value, _next) => {
println!("value: {}", value);
}
Node::Nil => {
println!("nil");
}
}
}
我的问题是为什么我需要在 match 语句中使用&
? 如果我删除&
我会得到以下编译错误:
error[E0507]: cannot move out of an `Rc`
--> src/main.rs:11:11
|
11 | match *list {
| ^^^^^ help: consider borrowing here: `&*list`
12 | Node::Cons(value, _next) => {
| -----
| |
| data moved here
| move occurs because `_next` has type `Rc<Node>`, which does not implement the `Copy` trait
我不明白上面的错误信息。 我认为由于list
是一个 Rc 指针,我应该取消引用list
以匹配Node
变量。 另一方面,如果我在 Node 中删除递归定义(只保留i32
)或使用Box
而不是Rc
,那么我可以匹配*list
。
首先,让我们给出一个简单的解决方案:因为您不需要next
,所以您可以不尝试获取它:
match *list {
Node::Cons(value, _) => {
println!("value: {}", value);
}
Node::Nil => {
println!("nil");
}
}
这也暗示了为什么您的代码在没有&
的情况下无法工作:您请求将节点移动到其组件中,第二个不是Copy
,这意味着必须首先将节点移出其Rc
。
但是你通常不会将一个值移出它的Rc
:一个Rc
应该是共享的,所以你不能在不首先检查没有其他智能引用的情况下删除该值。
如果你真的想从Rc
中删除节点,你可以这样做
if let Ok(node) = Rc::<Node>::try_unwrap(list) {
match node {
Node::Cons(value, next) => {
println!("value: {}", value);
// you may use next here
}
Node::Nil => {
println!("nil");
}
}
}
但大多数情况下,如果您有Rc
,您想要查看它(就像您的代码对&
所做的那样),或者尝试使用get_mut
获取可变引用,这只有在没有其他引用时才有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.