2015-06-01 13 views
6

sto elaborando semplici stringhe di formato "1s: 1d", "100: 5000", ecc con questa espressione regolare:Regex metodo di cattura iteratore si muove iteratore

let retention_matcher = regex::Regex::new({r"^(\d+)([smhdy])?:(\d+)([smhdy])?$"}).unwrap(); 

So che questo regex dovrebbe corrispondere una sola volta in modo Voglio eseguire la regex per le catture e controllare il numero di catture.

let iter = retention_matcher.captures_iter(ts); 
    let count = iter.count(); 
    println!("iter.count(): {}", count); 

    let _ : Vec<Option<(u64,u64)>> = iter.map(|regex_match| { 
     let retval = retention_spec_to_pair(regex_match); 
     println!("precision_opt: {:?}", retval); 
     retval 
    }).collect(); 

Il problema è che il metodo count() muove iter e non posso più usarlo.

src/bin/whisper.rs:147:42: 147:46 error: use of moved value: `iter` 
src/bin/whisper.rs:147   let _ : Vec<Option<(u64,u64)>> = iter.map(|regex_match| { 
                   ^~~~ 
src/bin/whisper.rs:144:21: 144:25 note: `iter` moved here because it has type `regex::re::FindCaptures<'_, '_>`, which is non-copyable 
src/bin/whisper.rs:144   let count = iter.count(); 

Questo non ha senso per me. Il metodo count dovrebbe restituire solo un valore copiabile usize e non lo spostamento iter? Come posso risolvere questo problema?

+1

Se avete solo bisogno una serie di acquisizioni, quindi utilizzare 'retention_matcher.captures (TS)'. Il suo contratto sembra corrispondere esattamente al tuo caso d'uso. (In effetti, la tua regex è completamente ancorata, quindi potrebbe sempre produrre una sola corrispondenza per una stringa particolare.) Non c'è bisogno di muckare con gli iteratori. :-) – BurntSushi5

risposta

7

Sospetto che stiate pensando a iter come a una sequenza astratta di catture. È più accurato pensare che rappresenti una posizione all'interno di una sequenza astratta di catture. La cosa fondamentale che qualsiasi iteratore sa fare è passare all'elemento successivo in una sequenza; cioè, puoi avanzare la posizione e ottenere l'elemento successivo nella sequenza.

count sposta iter perché per contare quanti elementi sono presenti nella sequenza, è necessario generare l'intera sequenza. Questo necessariamente modifica l'iteratore passandolo attraverso l'intera sequenza. Si muove perché dopo aver chiamato count, l'iteratore in realtà non è più utile. Per definizione, deve essere passato alla fine della sequenza!

Purtroppo, non sembra che il tipo di iteratore in questione (FindCaptures) sia Clone, quindi non è sufficiente crearne una copia.

La soluzione sarebbe quella di ristrutturare il codice per non chiamata count. Se si desidera ottenere il primo elemento e garantire non ci sono più, il modello più semplice sarebbe:

let mut iter = ...; 
if let Some(regex_match) = iter.next() { 
    // Ensure that there is no next element. 
    assert_eq!(iter.next(), None); 

    // process regex_match ... 
}