如何在不需要分配给新变量的情况下为链表实现前置?

How to implement prepend for a linked list without needing to assign to a new variable?

有人告诉我如何实现链表:

enum List {
    Cons(u32, Box<List>),
    Nil,
}

impl List {
    fn prepend(self, elem: u32) -> List {
        Cons(elem, Box::new(self))
    }
}

当我想使用prepend时,我需要做以下事情:

list = list.prepend(1);

但是,我想创建一个不需要每次都创建新变量的函数prepend returns。我只想使用 prepend:

更改 list 变量本身
list.prepend(1);

这是我想出的一种实现方式,但并不正确:

fn my_prepend(&mut self, elem: u32) {
    *self = Cons(elem, Box::new(*self));
}

错误是:

error[E0507]: cannot move out of borrowed content

List::prepend 必须 移动 self 因为这确实是正在发生的事情。链表的新头是一个新对象,旧头移到堆上,使旧变量无效。

my_prepend 中,您有一个对 self 的可变引用,但随后您移动了它的值,因此 self 引用变得无效。尽管它只是暂时无效,但这就是消息 "cannot move out of borrowed content" 所抱怨的。

解决这个问题的一种方法是将 self 移出到一个变量中并 同时 将其替换为 Nil,这样 self 引用永远不会无效。您可以使用 mem::replace:

use std::mem;

fn my_prepend(&mut self, elem: u32) {
    // Move the value of self into head, and leave self as Nil so it isn't invalid
    let head = mem::replace(self, List::Nil);
    // Reassign to self with the prepended value
    *self = head.prepend(elem);
}