iter()
, iter_mut()
の実装。
成果物
コード
impl<T> LinkedList<T> { ... pub fn iter(&self) -> Iter<'_, T> { Iter { next: self.head.as_ref().map(|node| &**node) } } pub fn iter_mut(&mut self) -> IterMut<'_, T> { IterMut { next: self.head.as_mut().map(|node| &mut **node) } }
pub struct Iter<'a, T> { next: Option<&'a Node<T>> } pub struct IterMut<'a, T> { next: Option<&'a mut Node<T>> } impl<'a, T> std::iter::Iterator for Iter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option<Self::Item> { self.next.map(|node| { self.next = node.next.as_ref().map(|node| &**node); &node.item }) } } impl<'a, T> std::iter::Iterator for IterMut<'a, T> { type Item = &'a mut T; fn next(&mut self) -> Option<Self::Item> { self.next.take().map(|node| { self.next = node.next.as_mut().map(|node| &mut **node); &mut node.item }) } }
テストコード
#[test] fn LinkedList_iter() { let mut list: LinkedList<i32> = LinkedList::new(); let expecteds = vec![10,20,30]; for i in expecteds.iter() { list.push(*i); } for (i, value) in list.iter().enumerate() { assert_eq!(*value, expecteds[i]) } for (i, value) in list.iter().enumerate() { assert_eq!(*value, expecteds[i]) } list.clear(); let datas = vec![1,2,3]; let expecteds = vec![1,3]; for i in datas.iter() { list.push(*i); } for (i, value) in list.iter().filter(|item| **item%2==1).enumerate() { assert_eq!(*value, expecteds[i]) } } #[test] fn LinkedList_iter_mut() { let mut list: LinkedList<i32> = LinkedList::new(); let expecteds = vec![10,20,30]; for i in expecteds.iter() { list.push(*i); } for (i, value) in list.iter_mut().enumerate() { assert_eq!(*value, expecteds[i]) } for (i, value) in list.iter_mut().enumerate() { assert_eq!(*value, expecteds[i]) } list.clear(); let datas = vec![1,2,3]; let expecteds = vec![1,3]; for i in datas.iter() { list.push(*i); } for (i, value) in list.iter_mut().filter(|item| **item%2==1).enumerate() { assert_eq!(*value, expecteds[i]) } let expecteds = vec![2,3,4]; for (i, value) in list.iter_mut().enumerate() { *value += 1; } for (i, value) in list.iter_mut().enumerate() { assert_eq!(*value, expecteds[i]) } }
以下のことを確認した。
- 何度でも参照を得られる(所有権ムーブしない(
LinkedList
やNode
やそれらフィールドの)) filter
メソッドを使って絞りこめるiter_mut
は値を変更できる(可変性がある)
罠
IterMut
のnext
ではOption.take()
で所有権をムーブさせてからでないと可変参照を返せない
所感
ついにできた(泣)
ところで前回の参考コードと比較するといくつか疑問がある。
Drop
トレイトって実装しないとメモリ解放されないの?
さらに独自の疑問。
- 逆順に取得できなの?
list[2 .. 7]
みたいに範囲取得できないの?
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- rustc 1.34.2 (6c2484dc3 2019-05-13)
- cargo 1.34.0 (6789d8a0a 2019-04-01)
$ uname -a Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux
前回まで
- Rust学習まとめ(ドキュメント)
- Rust自習(じゃんけんゲーム1)
- Rust自習(双方向リスト1)
- Rust自習(単方向リスト1)
- Rust自習(単方向リスト2)
- Rust自習(単方向リスト3)
- Rust自習(単方向リスト4)
- Rust自習(単方向リスト5)
- Rust自習(単方向リスト6)
- Rust自習(単方向リスト7)
- Rust自習(リストのインタフェースを考える)
- Rust自習(連結リスト1)
- Rust自習(連結リスト2)
- Rust自習(連結リスト3)
- Rust自習(連結リスト4)
- Rust自習(連結リストの取得系インタフェース考察)
- Rust自習(連結リスト5)
- Rust自習(連結リストの取得系インタフェース考察2)
- Rust自習(連結リスト6)
- Rust自習(連結リスト7)
- Rust自習(連結リスト8)
- Rust自習(連結リスト9)
- Rust自習(変数名でイテレートする方法)
- Rust自習(iter、iter_mut実装方法)