3.2.3 Testcase: linked-list

enums는 linked-list를 만드는데 범용적으로 사용된다.

use List::*;

enum List {
    // Cons: 튜플 구조체로 보관하는 것은 요소와 다음 노드 포인터
    Cons(u32, Box<List>),
    // Nil: 노드로 linked list의 끝을 식별
    Nil,
}

// 메소드는 enum에 접목될 수 있다. 
impl List {
    // 빈 리스트를 생성. 
    fn new() -> List {
        // `Nil`는 `List` 타입
        Nil
    }

    // list를 취하고 동일 list와 새 요소를 전면에 추가해 반환.
    fn prepend(self, elem: u32) -> List {
        // `Cons` 또한 List 타입을 갖는다.
        Cons(elem, Box::new(self))
    }

    // list의 길이 반환. 
    fn len(&self) -> u32 {
        // `self`가 일치해야 되는 이유는 이 메소드의 행위가 
        // `self`의 변수형에 달려있기 때문이다. 
        // `self`는  `&List`타입이고, `*self`는 `List`타입이고, 
        // 정확한 타입 `T`이 참조 `&T`보다 match에서 선호된다
        match *self {
            // 꼬리에 대한 소유권을 얻을 수 없는 이유는 `self`가 대여중이기 때문이다;
            // 대신 꼬리에 대한 참조를 빌리자.
            Cons(_, ref tail) => 1 + tail.len(),
            // 기본 상태: 빈 list는 0의 길이를 갖는다.
            Nil => 0
        }
    }

    // 반환하는 것은 list를 string으로 표현한 것(heap 할당된).
    fn stringify(&self) -> String {
        match *self {
            Cons(head, ref tail) => {
                // `format!`은 `print!`와 유사하지만, 
                // 반환하는 것은 콘솔 출력 대신 힙에 할당된 string이다.
                // `format!` is similar to `print!`, but returns a heap
                // allocated string instead of printing to the console
                format!("{}, {}", head, tail.stringify())
            },
            Nil => {
                format!("Nil")
            },
        }
    }
}

fn main() {
    // 빈 linked list를 만든다.
    let mut list = List::new();

    // 요소 몇 개를 추가한다.
    list = list.prepend(1);
    list = list.prepend(2);
    list = list.prepend(3);

    // list의 마지막 상태를 보여준다.
    println!("linked list has length: {}", list.len());
    println!("{}", list.stringify());
}

See also:

Box and methods

results matching ""

    No results matching ""