반복자와 소유권

러스트의 소유권 모델은 많은 API에 반영이 되어 있습니다. 예를들어 Iterator 와 IntoIterator 같은 트레잇이 있습니다.

Iterator

트레잇은 타입에 대한 행동(메서드)를 설명한다는 점에서 인터페이스와 유사합니다. Iterator는 단순히 None이 나올때까지 next를 호출하는 것이 가능하다는 것을 나타내는 트레잇입니다:

#![allow(unused)]
fn main() {
pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}
}

Iterator 트레잇은 이렇게 사용합니다:

fn main() {
    let v: Vec<i8> = vec![10, 20, 30];
    let mut iter = v.iter();

    println!("v[0]: {:?}", iter.next());
    println!("v[1]: {:?}", iter.next());
    println!("v[2]: {:?}", iter.next());
    println!("No more items: {:?}", iter.next());
}

반복자가 반환하는 값들은 타입이 뭘까요? 여기서 답을 테스트 해 보세요:

fn main() {
    let v: Vec<i8> = vec![10, 20, 30];
    let mut iter = v.iter();

    let v0: Option<..> = iter.next();
    println!("v0: {v0:?}");
}

왜 이런 타입이 사용되는 것일까요?

IntoIterator

Iterator 트레잇은 생성된 반복자를 _사용_하는 방법을 알려줍니다. 반면 IntoIterator 트레잇은 반복자를 _생성_하는 방법을 알려줍니다:

#![allow(unused)]
fn main() {
pub trait IntoIterator {
    type Item;
    type IntoIter: Iterator<Item = Self::Item>;

    fn into_iter(self) -> Self::IntoIter;
}
}

IntoIterator의 모든 구현은 반드시 다음의 두 타입을 선언해야합니다:

  • Item: i8과 같이 반복되는 값의 타입,
  • IntoIter: into_iter 메서드에서 반환되는 Iterator타입.

IntoIter에는 Item이 연결되어 있음을 주목하세요. IntoIter 반복자는 Item 타입의 데이터를 가리켜야 합니다. 즉, 반복자는 Option<Item>을 리턴합니다

이전과 마찬가지로, 반복자가 반환하는 타입은 무엇입니까?

fn main() {
    let v: Vec<String> = vec![String::from("foo"), String::from("bar")];
    let mut iter = v.into_iter();

    let v0: Option<..> = iter.next();
    println!("v0: {v0:?}");
}

배열과 for 반복문

자, 이제 우리는 Iterator와 IntoIterator를 알았으므로 for 루프를 만들 수 있습니다. for 루프는 into_iter()를 호출하여 반복자를 만든 다음 그 반복자를 이용하여 요소들을 반복해서 접근합니다:

fn main() {
    let v: Vec<String> = vec![String::from("foo"), String::from("bar")];

    for word in &v {
        println!("word: {word}");
    }

    for word in v {
        println!("word: {word}");
    }
}

매 루프에서 word의 타입은 무엇입니까?

위 코드에서 실험 해 본 후, 다음 문서를 참조해서 답변을 확인하시기 바랍니다:impl IntoIterator for &Vec<T>, impl IntoIterator for Vec<T>