やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rust自習(連結リスト10)

 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]) }
    }

 以下のことを確認した。

  • 何度でも参照を得られる(所有権ムーブしない(LinkedListNodeやそれらフィールドの))
  • filterメソッドを使って絞りこめる
  • iter_mutは値を変更できる(可変性がある)

  • IterMutnextではOption.take()で所有権をムーブさせてからでないと可変参照を返せない

所感

 ついにできた(泣)

 ところで前回の参考コードと比較するといくつか疑問がある。

  • Dropトレイトって実装しないとメモリ解放されないの?

 さらに独自の疑問。

  • 逆順に取得できなの?
  • list[2 .. 7]みたいに範囲取得できないの?

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで