做 too many list 的单链表。Iter 和 IterMut 用了不同与文章的写法。
结果 Iter 可以,IterMut 败给了生存期检查。
我感觉生存期这方面 Iter 和 IterMut 是一样的啊,他要是报cannot borrow
x as mutable more than once at a time
倒还好理解一些。
IterMut 这种错误怎么解决?
struct Node<T> {
elem: T,
next: Link<T>,
}
type Link<T> = Option<Box<Node<T>>>;
pub struct LinkedStack<T> {
head: Link<T>,
}
pub struct Iter<'a, T>(&'a Link<T>);
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
match self.0 {
None => None,
Some(node) => {
self.0 = &node.next;
Some(&node.elem)
}
}
}
}
pub struct IterMut<'a, T>(&'a mut Link<T>);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
match self.0 {
None => None,
Some(node) => {
self.0 = &mut node.next;
Some(&mut node.elem)
}
}
}
}
// too many list 的写法 从 map 改回 match 了
pub struct IterMutBook<'a, T>(Option<&'a mut Node<T>>);
impl<'a, T> Iterator for IterMutBook<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
match self.0.take() {
None => None,
Some(node) => {
self.0 = node.next.as_deref_mut();
Some(&mut node.elem)
}
}
}
}
附编译错误
error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
--> too-many-linked-list\src\linked_stack\iter_x.rs:30:18
|
30 | Some(node) => {
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 27:13...
--> too-many-linked-list\src\linked_stack\iter_x.rs:27:13
|
27 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> too-many-linked-list\src\linked_stack\iter_x.rs:30:18
|
30 | Some(node) => {
| ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 25:6...
--> too-many-linked-list\src\linked_stack\iter_x.rs:25:6
|
25 | impl<'a, T> Iterator for IterMut<'a, T> {
| ^^
note: ...so that reference does not outlive borrowed content
--> too-many-linked-list\src\linked_stack\iter_x.rs:31:26
|
31 | self.0 = &mut node.next;
| ^^^^^^^^^^^^^^
1
共 4 条评论, 1 页
评论区
写评论我是指 IterMut 本身可能会改变链表长度。&mut Link 不仅能改变 node.elem,还能改变 node.next。写着写着发现 IterMutBook 也可能发生这种情况,是我想多了。
--
👇
viruscamp: 有启发。
因为 &T 是 Copy 的, 所以 match 表达式和 match arm 的变量可以共存。
而 &mut T 是 !Copy 的, 所以 match 表达式在 match arm 内无效。
至于你说,这种实现有问题,具体是什么问题呢?能有伪代码描述吗?
我觉得没有问题,是因为持有 IterMut 时,是不可能调用 list.push list.pop 等函数改变长度的。
而且我们可以在 IterMut 内实现各种修改链表结构的操作
--
👇
Grobycn: 参考 https://users.rust-lang.org/t/cannot-infer-appropriate-lifetime-for-mutable-reference/17485/3
另外说一句,
pub struct IterMut<'a, T>(&'a mut Link<T>);
这种实现是有问题的,第三方使用者并不能确定 IterMut 使用之后链表长度是否发生变化。有启发。
因为 &T 是 Copy 的, 所以 match 表达式和 match arm 的变量可以共存。
而 &mut T 是 !Copy 的, 所以 match 表达式在 match arm 内无效。
至于你说,这种实现有问题,具体是什么问题呢?能有伪代码描述吗?
我觉得没有问题,是因为持有 IterMut 时,是不可能调用 list.push list.pop 等函数改变长度的。
而且我们可以在 IterMut 内实现各种修改链表结构的操作
--
👇
Grobycn: 参考 https://users.rust-lang.org/t/cannot-infer-appropriate-lifetime-for-mutable-reference/17485/3
另外说一句,
pub struct IterMut<'a, T>(&'a mut Link<T>);
这种实现是有问题的,第三方使用者并不能确定 IterMut 使用之后链表长度是否发生变化。用 unsafe 勉强实现了。 测试没有问题。
参考 https://users.rust-lang.org/t/cannot-infer-appropriate-lifetime-for-mutable-reference/17485/3
另外说一句,
pub struct IterMut<'a, T>(&'a mut Link<T>);
这种实现是有问题的,第三方使用者并不能确定 IterMut 使用之后链表长度是否发生变化。