如何实现链表中特定元素的设置值?

How to implement setting value of a specific element in linked list?

我正在通过实现单个链表来学习 Rust。我已经阅读了 Learning Rust With Entirely Too Many Linked Lists 中的第 2 章。我想实现一个函数来通过索引设置列表中特定元素的值。到目前为止,这是我的代码:

pub struct List {
    head: Link,
}

enum Link {
    Empty,
    More(Box<Node>),
}

struct Node {
    elem: i32,
    next: Link,
}

impl List {
    /// Replaces the element at the specified position in this list with the specified element.
    pub fn set(&mut self, index: usize, elem: i32) -> Result<(), &str> {
        // Start from the first node where index is 0
        let mut id: usize = 0;
        let mut curr_node: &Link = &self.head;
        while let Link::More(mut node) = curr_node {
            curr_node = &node.next;
            id += 1;
            if id == index {
                node.elem = elem;
                break;
            }
        }
        if id < index {
            return Err("Invalid index");
        }
        Ok(())
    }
}

编译器发出 2 个编译错误:

error[E0507]: cannot move out of `curr_node.0` which is behind a shared reference
  --> src/lib.rs:21:42
   |
21 |         while let Link::More(mut node) = curr_node {
   |                              --------    ^^^^^^^^^
   |                              |
   |                              data moved here
   |                              move occurs because `node` has type `Box<Node>`, which does not implement the `Copy` trait

error[E0597]: `node.next` does not live long enough
  --> src/lib.rs:22:25
   |
21 |         while let Link::More(mut node) = curr_node {
   |                                          --------- borrow later used here
22 |             curr_node = &node.next;
   |                         ^^^^^^^^^^ borrowed value does not live long enough
...
28 |         }
   |         - `node.next` dropped here while still borrowed

Playground link

我该如何正确实施?

当我看到你的问题的标题时,我立即想 post link 那本“通过太多 linked 列表学习 Rust” 的书,但我看到你了已经开始了:)

啊,太乱了,不是吗?那么在您的情况下,解决方案非常简单。

首先,curr_node 的类型应该是 &mut Link,因此也需要用 &mut self.head 初始化,因为我们需要一个 mutable参考。

接下来,在您的 while 循环中,您使用 模式匹配 将节点的值绑定到您的变量 node。但是,模式匹配默认 将匹配的值 移动到变量中,这就是编译器抱怨的原因:您不能直接将元素移出结构。

而不是移动,我们只是想获取一个 reference 到节点,所以我们说 while let Link::More(ref mut node) = curr.node { ... }

最后是 curr_node = &mut node.next 因为我们又需要一个 可变 引用。

Playground Link