2014-09-06 28 views
9

İçine basitleştiren bir sorunla karşılaştık aşağıdadır: Bu hata üretirKendisini değiştiren ve sonra kendi başına bir referans veren bir Yineleyici yazabilir miyim?

struct MyIter { 
    vec: Vec<i8>, 
} 

fn fill_with_useful_data(v: &mut Vec<i8>) { 
    /* ... */ 
} 

impl<'a> Iterator for MyIter { 
    type Item = &'a [i8]; 

    fn next(&mut self) -> Option<&'a [i8]> { 
     fill_with_useful_data(&mut self.vec); 

     Some(&self.vec) 
    } 
} 

fn main() { 
    for slice in (MyIter { vec: Vec::new() }) { 
     println!("{}", slice); 
    } 
} 

:

error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates 
--> src/main.rs:9:6 
    | 
9 | impl<'a> Iterator for MyIter { 
    |  ^^ unconstrained lifetime parameter 

fikri yineleyici kendi alanlarında ve en yansıtan işin bir demet yapmasıdır Her adımda, çağrı koduna kendi başına bir referans verir. Bu durumda, onu referansın yerine devletin bir kopyasını elde etmek için modelleyebilirdim, ancak bunun mümkün olmadığını ya da sakıncalı bir şekilde pahalı olduğunu varsayalım. ariyet denetleyicisi vermiştir referans hala yineleyici durumunu incelemek için kullanılabilir ederken .next() yine aradı olmadığından emin olun çünkü

Sezgisel bu bir problem olmamalı, ancak Iterator özellik sağlamak için görünmüyor Bu tür bir şey doğrudan. Yineleyicideki vektöre sadece bir referansa dayanmak gibi birtakım permütasyonlarda bile veya iteratörün daha önceki tipte pişirilen yaşamları almak için bir referans ya da bir şey yapması durumunda, borç kontrolöründen bir şey alamıyorum.

"Iterators yielding mutable references" blogpostunu okudum ancak değiştirilebilen başvurular içermeyen benim sorunum için geçerli olup olmadığından emin değilim.

cevap

10

Bu mümkün değil. İzin verildiyse, next'u tekrar arayabilir ve böylece & aracılığıyla da görülebilen verileri değiştirebilir veya hatta referansı tamamen geçersiz kılabilir. Bunun nedeni, self nesnesinin kendisi ile döndürülen başvuru arasında bir bağlantı olmamasıdır: bağlantı veren açık ömür yoktur. derleyici bu konuda akıl ve bu sadece alır jenerik kodu olarak izin verilmez özelliği imzası farklıdır, self içine referans sonraki Ancak

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

gibi bir imza ihtiyacı dönen izin vermek için

T: Iterator<...>, bazı T için dönüş değeri kullanımında farklı gereksinimlerin olduğunu söyleyemez; hepsi aynı şekilde ele alınmalıdır.

Iterator özelliği, .collect gibi yineleyici bağdaştırıcıların doğru ve güvenli olması için gereken yineleyici nesnesinden bağımsız olarak döndürülen değerler için tasarlanmıştır. Bu, birçok kullanım için gerekli olandan daha kısıtlayıcıdır (örneğin, for döngüsünün içinde geçici bir kullanım), ancak tam olarak şu andaki durumdur. Bu özelliği/döngüyü şu anda uygun hale getirmek için gerekli araçlara sahip olduğumuzu düşünmüyorum (özellikle, daha yüksek sıra ömrü olan ilişkili türlere ihtiyacımız var), ama belki de gelecekte.

+0

Pekala, sadece "Yineleyici" yi kullanmayı bıraktım ve makro için kendi öz döngüsünü yaptım. .collect() 'ın nasıl çalışacağını düşünmedim. – ben

+0

Bu, 'for' döngüsünü kullanamayacağınız geçişler için de iyidir:' Bazılarına izin ver (element) = iter.next() {... ' – bluss

+1

Gelecekte referans için bu tür yineleyici (' fn next (& 'bir öz) ') genellikle * akışlı yineleyici * olarak adlandırılır. Bazı tartışma örnekleri [1] (https://users.rust-lang.org/t/returning-borrowed-values-from-an-iterator/1096), [2] (https://www.reddit.com/r/rust/comments/2t1rxx/more_general_iterator_trait /) ve [bir formunu uygulayan bir kasa] (https://github.com/sfackler/streaming-iterator). – Shepmaster

İlgili konular