.iter() 메서드
IntoIterator는 반복자를 만들기 위해 self를 **소비(Consume)**합니다.
이는 한편으로 장점이 됩니다. 반복자로부터 소유권이 있는(Owned) 값을 직접 얻을 수 있기 때문입니다. 예를 들어, Vec<Ticket>에서 .into_iter()를 호출하면 각 티켓의 값을 직접 반환하는 반복자를 얻게 됩니다.
하지만 동시에 단점도 있습니다. into_iter()를 호출하고 나면 원본 컬렉션을 더 이상 사용할 수 없게 되기 때문입니다. 하지만 실제로는 컬렉션을 없애지 않고, 그 안에 담긴 값들을 **참조(Reference)**만 하면서 순회하고 싶은 경우가 훨씬 많습니다. Vec<Ticket>이라면 &Ticket을 얻고 싶은 것이죠.
그래서 대부분의 컬렉션은 요소에 대한 참조를 반환하는 .iter() 메서드를 따로 제공합니다.
let numbers: Vec<u32> = vec![1, 2];
// 여기서 `n`은 `&u32` 타입입니다.
for n in numbers.iter() {
// [...]
}
이 패턴은 컬렉션의 참조 자체에 대해 IntoIterator를 구현함으로써 더 단순하게 만들 수 있습니다. 위 예시라면 &Vec<u32>에 대해 IntoIterator를 구현하는 식입니다. 표준 라이브러리에는 이미 이 구현이 되어 있기 때문에 아래와 같은 코드가 가능합니다.
let numbers: Vec<u32> = vec![1, 2];
// 여기서 `n`은 `&u32` 타입입니다.
// 굳이 `.iter()`를 명시적으로 호출할 필요 없이,
// `for` 루프에 `&numbers`를 넘겨주는 것만으로 충분합니다.
for n in &numbers {
// [...]
}
Rust에서는 다음과 같이 두 가지 옵션을 모두 제공하는 것이 **관용적(Idiomatic)**입니다.
- 컬렉션의 참조(
&T)에 대한IntoIterator구현 - 컬렉션 요소의 참조를 반환하는
.iter()메서드 제공
첫 번째 방식은 for 루프에서 쓰기 아주 편리하고, 두 번째 방식은 의도가 더 명확하게 드러나며 다른 여러 상황에서도 유연하게 사용할 수 있습니다.
Exercise
The exercise for this section is located in 06_ticket_management/05_iter