我正在学习Rust,并尝试实现一个单向链表。一切都很顺利,直到我尝试实现从链表中删除末尾节点的函数。
链表的定义如下:
pub struct LinkedList<T> {
head: Link<T>,
}
#[derive(Debug)]
struct Node<T> {
ele: T,
next: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;
我最初尝试使用while let
但失败了:
impl<T: Copy + std::fmt::Debug> LinkedList<T> {
pub fn pop_tail_not_working_1(&mut self) -> Option<T> {
let mut cur = &mut self.head;
while let Some(node) = cur {
if node.next.is_none() {
return cur.take().map(|tail| tail.ele);
}
cur = &mut node.next;
}
None
}
}
带有错误信息
error[E0499]: cannot borrow `*cur` as mutable more than once at a time
--> src/linked_list.rs:66:24
|
64 | while let Some(node) = cur {
| ---- first mutable borrow occurs here
65 | if node.next.is_none() {
66 | return cur.take().map(|tail| tail.ele);
| ^^^
| |
| second mutable borrow occurs here
| first borrow later used here
然后我尝试了循环+匹配
,但仍然失败了:
impl<T: Copy + std::fmt::Debug> LinkedList<T> {
pub fn pop_tail_not_working_2(&mut self) -> Option<T> {
let mut cur = &mut self.head;
loop {
match cur {
None => return None,
Some(node) => {
if node.next.is_none() {
return cur.take().map(|tail| tail.ele);
}
cur = &mut node.next;
}
}
}
}
}
出现相似的错误信息:
error[E0499]: cannot borrow `*cur` as mutable more than once at a time
--> src/linked_list.rs:54:32
|
52 | Some(node) => {
| ---- first mutable borrow occurs here
53 | if node.next.is_none() {
54 | return cur.take().map(|tail| tail.ele);
| ^^^
| |
| second mutable borrow occurs here
| first borrow later used here
最后,我尝试了match
守卫,并且它起作用了。
impl<T: Copy + std::fmt::Debug> LinkedList<T> {
pub fn pop_tail(&mut self) -> Option<T> {
let mut cur = &mut self.head;
loop {
match cur {
None => return None,
Some(node) if node.next.is_none() => {
return cur.take().map(|tail| tail.ele);
}
Some(node) => cur = &mut node.next,
}
}
}
}
我不确定为什么第三种实现方法可行而前两种不行,我认为它们都使用了同样的逻辑。特别是,我对“先借后用”这个短语非常困惑,我无法理解为何在第二个可变借用发生时会使用第一个借用。
too-many-list
没有实现类似的功能,即从列表中删除尾部或任意链接的函数。 - DistributedSlacker