繁体   English   中英

使用 Rc 将 rust 枚举与递归定义匹配

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM