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()); }