やってみる

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

Rust自習(単方向リスト7)

 clearメソッド実装。

成果物

clearメソッド

 リストのノードを全削除する。

    pub fn clear(&mut self) {
        // 末尾ノードから削除していく
        fn reverse_drop<T>(node: &mut Option<Box<Node<T>>>) {
            if let Some(ref mut _n) = *node {
                reverse_drop(&mut _n.next);
                std::mem::replace(&mut *node, None);
            }
        }
        reverse_drop(&mut self.head);
    }

テストコード

    #[test]
    fn OnewayList_clear_3() {
        let mut list: OnewayList<i32> = OnewayList::new();
        list.clear();
        assert_eq!(list.head, None);
        list.push(0);
        list.push(1);
        list.push(2);
        assert_eq!(list.head, Some(Box::new(Node { item: 0, next: 
            Some(Box::new(Node { item: 1, next: 
                Some(Box::new(Node { item: 2, next: None }))
            }))
        })));
        list.clear();
        assert_eq!(list.head, None);
    }

解説

    pub fn clear(&mut self) {
        // 末尾ノードから削除していく
        fn reverse_drop<T>(node: &mut Option<Box<Node<T>>>) {
            if let Some(ref mut _n) = *node {
                reverse_drop(&mut _n.next);
                std::mem::replace(&mut *node, None);
            }
        }
        reverse_drop(&mut self.head);
    }

 処理はreverse_drop内部関数の実行のみ。そしてその関数の処理はコメントの通り、末尾ノードから順に削除していく。push, removeメソッド同様、再帰によって末尾ノードを探している。大きな違いは、戻り値が必要がないこと。

 削除はstd::mem::replace関数でやる。元々あったノードのインスタンスが帰ってくるが、それをスコープ内で死なせることで削除する。再帰で末尾のほうから先に処理するのがポイント。

対象環境

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

前回まで