# IterMut以及完整代码 上一章节中我们讲到了要为 `List` 实现三种类型的迭代器并实现了其中两种: `IntoIter` 和 `Iter`。下面再来看看最后一种 `IterMut`。 再来回顾下 `Iter` 的实现: ```rust impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { /* stuff */ } } ``` 这段代码可以进行下脱糖( desugar ): ```rust impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; fn next<'b>(&'b mut self) -> Option<&'a T> { /* stuff */ } } ``` 可以看出 `next` 方法的输入和输出之间的生命周期并没有关联,这样我们就可以无条件的一遍又一遍地调用 `next`: ```rust let mut list = List::new(); list.push(1); list.push(2); list.push(3); let mut iter = list.iter(); let x = iter.next().unwrap(); let y = iter.next().unwrap(); let z = iter.next().unwrap(); ``` 对于不可变借用而言,这种方式没有任何问题,因为不可变借用可以同时存在多个,但是如果是可变引用呢?因此,大家可能会以为使用安全代码来写 `IterMut` 是一件相当困难的事。但是令人诧异的是,事实上,我们可以使用安全的代码来为很多数据结构实现 `IterMut`。 先将之前的代码修改成可变的: ```rust pub struct IterMut<'a, T> { next: Option<&'a mut Node>, } impl List { pub fn iter_mut(&self) -> IterMut<'_, T> { IterMut { next: self.head.as_deref_mut() } } } impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; fn next(&mut self) -> Option { self.next.map(|node| { self.next = node.next.as_deref_mut(); &mut node.elem }) } } ``` ```shell $ cargo build error[E0596]: cannot borrow `self.head` as mutable, as it is behind a `&` reference --> src/second.rs:95:25 | 94 | pub fn iter_mut(&self) -> IterMut<'_, T> { | ----- help: consider changing this to be a mutable reference: `&mut self` 95 | IterMut { next: self.head.as_deref_mut() } | ^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0507]: cannot move out of borrowed content --> src/second.rs:103:9 | 103 | self.next.map(|node| { | ^^^^^^^^^ cannot move out of borrowed content ``` 果不其然,两个错误发生了。第一错误看上去很清晰,甚至告诉了我们该如何解决: ```rust pub fn iter_mut(&mut self) -> IterMut<'_, T> { IterMut { next: self.head.as_deref_mut() } } ``` 但是另一个好像就没那么容易了。但是之前的代码就可以工作啊,为何这里就不行了? 原因在于有些类型可以 [Copy](https://course.rs/basic/ownership/ownership.html#拷贝浅拷贝),有些不行。而`Option` 和不可变引用 `&T` 恰恰是可以 Copy 的,但尴尬的是,可变引用 `&mut T` 不可以,因此这里报错了。 因此我们需要使用 `take` 方法来处理这种情况: ```rust fn next(&mut self) -> Option { self.next.take().map(|node| { self.next = node.next.as_deref_mut(); &mut node.elem }) } ``` ```shell $ cargo build ``` 老规矩,来测试下: ```rust #[test] fn iter_mut() { let mut list = List::new(); list.push(1); list.push(2); list.push(3); let mut iter = list.iter_mut(); assert_eq!(iter.next(), Some(&mut 3)); assert_eq!(iter.next(), Some(&mut 2)); assert_eq!(iter.next(), Some(&mut 1)); } ``` ```shell $ cargo test Running target/debug/lists-5c71138492ad4b4a running 6 tests test first::test::basics ... ok test second::test::basics ... ok test second::test::iter_mut ... ok test second::test::into_iter ... ok test second::test::iter ... ok test second::test::peek ... ok test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured ``` 最终,我们完成了迭代器的功能,下面是完整的代码。 ## 完整代码 ```rust pub struct List { head: Link, } type Link = Option>>; struct Node { elem: T, next: Link, } impl List { pub fn new() -> Self { List { head: None } } pub fn push(&mut self, elem: T) { let new_node = Box::new(Node { elem: elem, next: self.head.take(), }); self.head = Some(new_node); } pub fn pop(&mut self) -> Option { self.head.take().map(|node| { self.head = node.next; node.elem }) } pub fn peek(&self) -> Option<&T> { self.head.as_ref().map(|node| { &node.elem }) } pub fn peek_mut(&mut self) -> Option<&mut T> { self.head.as_mut().map(|node| { &mut node.elem }) } pub fn into_iter(self) -> IntoIter { IntoIter(self) } pub fn iter(&self) -> Iter<'_, T> { Iter { next: self.head.as_deref() } } pub fn iter_mut(&mut self) -> IterMut<'_, T> { IterMut { next: self.head.as_deref_mut() } } } impl Drop for List { fn drop(&mut self) { let mut cur_link = self.head.take(); while let Some(mut boxed_node) = cur_link { cur_link = boxed_node.next.take(); } } } pub struct IntoIter(List); impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { // access fields of a tuple struct numerically self.0.pop() } } pub struct Iter<'a, T> { next: Option<&'a Node>, } impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { self.next.map(|node| { self.next = node.next.as_deref(); &node.elem }) } } pub struct IterMut<'a, T> { next: Option<&'a mut Node>, } impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; fn next(&mut self) -> Option { self.next.take().map(|node| { self.next = node.next.as_deref_mut(); &mut node.elem }) } } #[cfg(test)] mod test { use super::List; #[test] fn basics() { let mut list = List::new(); // Check empty list behaves right assert_eq!(list.pop(), None); // Populate list list.push(1); list.push(2); list.push(3); // Check normal removal assert_eq!(list.pop(), Some(3)); assert_eq!(list.pop(), Some(2)); // Push some more just to make sure nothing's corrupted list.push(4); list.push(5); // Check normal removal assert_eq!(list.pop(), Some(5)); assert_eq!(list.pop(), Some(4)); // Check exhaustion assert_eq!(list.pop(), Some(1)); assert_eq!(list.pop(), None); } #[test] fn peek() { let mut list = List::new(); assert_eq!(list.peek(), None); assert_eq!(list.peek_mut(), None); list.push(1); list.push(2); list.push(3); assert_eq!(list.peek(), Some(&3)); assert_eq!(list.peek_mut(), Some(&mut 3)); list.peek_mut().map(|value| { *value = 42 }); assert_eq!(list.peek(), Some(&42)); assert_eq!(list.pop(), Some(42)); } #[test] fn into_iter() { let mut list = List::new(); list.push(1); list.push(2); list.push(3); let mut iter = list.into_iter(); assert_eq!(iter.next(), Some(3)); assert_eq!(iter.next(), Some(2)); assert_eq!(iter.next(), Some(1)); assert_eq!(iter.next(), None); } #[test] fn iter() { let mut list = List::new(); list.push(1); list.push(2); list.push(3); let mut iter = list.iter(); assert_eq!(iter.next(), Some(&3)); assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), Some(&1)); } #[test] fn iter_mut() { let mut list = List::new(); list.push(1); list.push(2); list.push(3); let mut iter = list.iter_mut(); assert_eq!(iter.next(), Some(&mut 3)); assert_eq!(iter.next(), Some(&mut 2)); assert_eq!(iter.next(), Some(&mut 1)); } } ```