やってみる

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

Rust自習(連結リスト7)

 nth_mutメソッド実装。

成果物

nth_mutメソッド

 指定した位置にあるノードが持つitemへの可変参照を返す。

 前回実装したnth_refの可変版。

コード

    /// 指定位置の可変参照を得る
    fn nth_mut(&mut self, index: usize) -> &mut T {
        fn get_ptr_from_idx<T>(ptr: &mut Option<Box<Node<T>>>, index: usize, count: usize) -> &mut Option<Box<Node<T>>> {
            if count < index {
                if ptr.is_some() { return get_ptr_from_idx(&mut ptr.as_mut().unwrap().next, index, count+1); }
                else { return ptr; }
            } else { return ptr; }
        }
        if let Some(ref mut _n) = get_ptr_from_idx(&mut self.head, index, 0) { return &mut (_n.item) }
        else { panic!("Out of index. index値が大きすぎます。index: {}", index); }
    }

テストコード

異常系

    #[test]
    #[should_panic(expected = "Out of index. index値が大きすぎます。index: 0")]
    fn LinkedList_nth_mut_out_of_index_0() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list.nth_mut(0);
    }
    #[test]
    #[should_panic(expected = "Out of index. index値が大きすぎます。index: 1")]
    fn LinkedList_nth_mut_out_of_index_1() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list.push(0);
        list.nth_mut(1);
    }

正常系

    #[test]
    fn LinkedList_nth_mut_1() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list.push(10);
        assert_eq!(*list.nth_mut(0), 10);
    }
    #[test]
    fn LinkedList_nth_mut_3() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list.push(10);
        list.push(11);
        list.push(12);
        let expecteds = vec![10, 11, 12];
        for (i, expected) in expecteds.iter().enumerate() {
            assert_eq!(*(list.nth_mut(i)), *expected);
        }
        for (i, expected) in expecteds.iter().enumerate() {
            assert_eq!(*(list.nth_mut(i)), *expected);
        }
    }

 値を変更できることを確認。今回の目玉。

    #[test]
    fn LinkedList_nth_mut_1_mutable() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list.push(10);
        assert_eq!(*(list.nth_mut(0)), 10);
        *list.nth_mut(0) = 11;
        assert_eq!(*(list.nth_mut(0)), 11);
    }

所感

 nth_mutlist[0] = 11;という表記で実現したいこと。どうやってやるのか。そもそも、できるのか。どうやってググればいいの?

 演算子オーバーロードだと思うのだが。ググってリンクを辿ったら以下をみつけた。

 std::ops::Indexトレイトのindexメソッドをオーバーライドすれば、list[0]で不変参照を得られる?

対象環境

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

前回まで