やってみる

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

Rust自習(連結リスト9)

 std::ops::IndexMutトレイトのindex_mutメソッドをオーバーライドした。

成果物

std::ops::IndexMutトレイト

 list[0] = 1;のようにインデックス指定で代入する書式の処理をオーバーライドする。

コード

impl<T> std::ops::IndexMut<usize> for LinkedList<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        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_index_mut_out_of_index_mut_0() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list[0] = 10;
    }
    #[test]
    #[should_panic(expected = "Out of index. index値が大きすぎます。index: 1")]
    fn LinkedList_index_mut_out_of_index_mut_1() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list.push(10);
        list[1] = 10;
    }

正常系

    #[test]
    fn LinkedList_index_mut_1() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list.push(10);
        assert_eq!(list[0], 10);
        list[0] = 11;
        assert_eq!(list[0], 11);
        list[0] += 1;
        assert_eq!(list[0], 12);
    }
    #[test]
    fn LinkedList_index_mut_3() {
        let mut list: LinkedList<i32> = LinkedList::new();
        list.push(10);
        list.push(20);
        list.push(30);
        assert_eq!(list[0], 10);
        assert_eq!(list[1], 20);
        assert_eq!(list[2], 30);
        list[0] = 11;
        list[1] = 21;
        list[2] = 31;
        assert_eq!(list[0], 11);
        assert_eq!(list[1], 21);
        assert_eq!(list[2], 31);
    }

 代入できる。つまり不変参照でなく可変参照である証。

 nth_ref, nth_mutメソッドを自前で実装したが、それらは戻り値が参照であるため、参照外しせねばならなかった。だがこのstd::ops::{Index, IndexMut}トレイトたちは[]書式で値を参照できるし代入できる。

所感

 やりたいことができるようになってきた。いい感じ。

対象環境

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

前回まで