2016-11-07 1 views
2

나는 Lifetime in Iterator impl을 알고 있지만 올바르게 이해할 수 있도록 좀 더 자세하게 설명하겠습니다.자체에 대한 참조를 반환하는 반복자

나는 &[0], &[0, 1], &[0, 1, 2] 등을 되 돌리는 무한한 Iterator를 쓰고 싶다. 나는 이것을 쓰고 싶습니다

struct Countings(Vec<usize>); 

impl Countings { 
    fn new() -> Countings { Countings(vec![]) } 
} 

impl Iterator for Countings { 
    type Item = &[usize]; 

    fn next(&mut self) -> Option<Self::Item> { 
     self.0.push(self.0.len()); 
     Some(self.0.as_slice()) 
    } 
} 

나는 유형 Countings::Item 평생이없는 수 없기 때문에.

error[E0106]: missing lifetime specifier 
--> src/lib.rs:8:17 
    | 
8 |  type Item = &[usize]; 
    |    ^expected lifetime parameter 

그래서 하나 추가합니다. 그것은 impl Iterator에 의해 구속되어야합니다. 즉, struct Countings에 평생 매개 변수가 필요합니다. 지금까지 내가 여기 :

struct Countings<'a>(Vec<usize>); 

impl<'a> Countings<'a> { 
    fn new() -> Countings<'a> { Countings(vec![]) } 
} 

impl<'a> Iterator for Countings<'a> { 
    type Item = &'a [usize]; 

    fn next(&mut self) -> Option<Self::Item> { 
     self.0.push(self.0.len()); 
     Some(self.0.as_slice()) 
    } 
} 

가 지금은 다른 오류가 있습니다

error[E0392]: parameter `'a` is never used 
--> src/lib.rs:1:18 
    | 
1 | struct Countings<'a>(Vec<usize>); 
    |     ^^ 
    | 
    = help: consider removing `'a` or using a marker such as `std::marker::PhantomData` 

나는 심각하게 고려해

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 
    --> src/lib.rs:14:25 
    | 
14 |    Some(self.0.as_slice()) 
    |       ^^^^^^^^ 
:

use std::marker::PhantomData; 

struct Countings<'a>(Vec<usize>, PhantomData<&'a [usize]>); 

impl<'a> Countings<'a> { 
    fn new() -> Countings<'a> { Countings(vec![], PhantomData) } 
} 

impl<'a> Iterator for Countings<'a> { 
    type Item = &'a [usize]; 

    fn next(&mut self) -> Option<Self::Item> { 
     self.0.push(self.0.len()); 
     Some(self.0.as_slice()) 
    } 
} 

을하지만 아무 소용이

질문 1 : "상충되는 요구 사항 에스"?

질문 2 : answer cited aboveIterator이 포장하는 것으로부터 Item을 빌려야한다고 말합니다. 나는 좋은 예인 std::slice::Windows의 출처를 읽었습니다. 그러나, 내 경우에는 이 호출 될 때마다 Vec을 돌연변이 화하려고합니다. 그게 가능하니?

답변

2

Question 1: What are the "conflicting requirements"?

당신이 반환하려고 차용은 약속대로, 수명 'a이 없습니다. 오히려, 그것은 self과 같은 수명을 가지고 있습니다. next에 대한 서명이 전체로 작성된 경우는 다음과 같습니다

fn next<'b>(&'b mut self) -> Option<&'a [usize]> 

반환 Option<&'b [usize]>가가에 대한 계약을 위반 한 사실이 없었다면 유효 할 것 (평생 'b 대신 'a의 포함) Iterator 특징. 그러나 결과가 삭제 될 때까지 self을 고정시킵니다. 즉 next 번을 두 번 호출 할 수없고 두 호출 결과를 함께 사용할 수 없습니다. next을 호출 할 때마다 이전에 반환 된 슬라이스가 무효화 될 수 있기 때문입니다. Vec을 누르면 추가 요소를위한 공간을 만들기 위해 메모리의 저장소가 재배치되어 슬라이스의 포인터가 더 이상 유효하지 않게됩니다.

Question 2: The answer cited above says that Item must borrow from something that the Iterator wraps. I have read the source for std::slice::Windows which is a good example. However, in my case I want to mutate the Vec each time next() is called. Is that possible?

그것은 Iterator 특성이 작업을 수행 할 수 없습니다, 그래서 당신은 당신의 구조체에 for 루프를 사용할 수 없습니다. 그러나, 당신은 일반적인 방법으로 (위에서 언급 한 것과 함께) 그것을 할 수 있습니다.

struct Countings(Vec<usize>); 

impl Countings { 
    fn new() -> Countings { Countings(vec![]) } 

    fn next<'a>(&'a mut self) -> &'a [usize] { 
     let item = self.0.len(); 
     self.0.push(item); 
     self.0.as_slice() 
    } 
} 
2

프란시스가 언급했듯이 반복되는 동안 기본 벡터를 수정할 수 없습니다.어떻게 든 바인딩 반복을 지정 할 수있을 것 인 경우에는, 다음 일이 훨씬 쉬울 것 :

  • 당신은 벡터 [0, 1, 2, ...]
  • 을 만든 다음 계속 성장하는 슬라이스를 반환하는 반복자를 만들 것 , 벡터

그냥 반복자의 길이까지 : 다음

struct EverGrowingIterator<'a, T: 'a> { 
    slice: &'a [T], 
    current: usize, 
} 

impl<'a, T> Iterator for EverGrowingIterator<'a, T> { 
    type Item = &'a [T]; 

    fn next(&mut self) -> Option<&'a [T]> { 
     if self.current >= self.slice.len() { 
      None 
     } else { 
      self.current += 1; 
      Some(&self.slice[0..self.current]) 
     } 
    } 
} 

그리고 :

fn ever_growing<'a, T>(slice: &'a [T]) -> EverGrowingIterator<'a, T> { 
    EverGrowingIterator { slice: slice, current: 0 } 
} 

fn main() { 
    let v = vec![0, 1, 2]; 
    for s in ever_growing(&v) { 
     println!("{:?}", s); 
    } 
} 

인쇄됩니다 : 당신은 무한한 성장이 적응해야하는 경우

[0] 
[0, 1] 
[0, 1, 2] 

, 당신은 참조를 유지하면서 성장하는 사용자 지정 컨테이너 (안 Vec)을 생성으로 볼 필요가 이전 조각에. RefCell<Vec<Box<[T]>>>과 같은 것을 사용할 수 있습니다.

+0

감사합니다. 당신의 대답은 유용한 것들을 가지고 있습니다. 두 가지 대답을 모두 받아 들일 수 있다면 프란시스의 대답은 내 두 가지 질문에 더 중점을 둡니다. – apt1002

관련 문제