2015-01-07 16 views
9

Czy ktoś mógłby mi pomóc przerobić ten kawałek kodu z nowych zamknięć odpakowanych:Jak przepisać kod do nowych zamknięć odpakowanych

struct Builder; 
pub fn build(rules: |params: &mut Builder|) -> Builder { 
    let mut builder = Builder::new(); 
    rules(&mut builder); 

    builder 
} 

starałem się pisać tak, ale mam błąd Żywotność:

pub fn build<F>(rules: F) -> Builder where F: FnOnce<(&mut Builder,),()> { 
    let mut builder = Builder::new(); 
    rules(&mut builder); 

    builder 
} 

valico/src/builder.rs:48:59: 48:71 error: missing lifetime specifier [E0106] 
valico/src/builder.rs:48  pub fn build<F>(rules: F) -> Builder where F: FnOnce<(&mut Builder,),()> { 
                        ^~~~~~~~~~~~ 

Jakie życie muszę podać? Simplified example in the sandbox.

+1

Close-wyborca: dlaczego jest to offtopic? – huon

Odpowiedz

12

Wymaga to higher rank trait bounds, w szczególności okresów wyższej rangi. Pełna nienazwana składnia byłaby F: for<'a> FnOnce<(&'a mut Builder,),()>.

Użycie całego cyklu życia funkcji nie działa, np. gdybyśmy mieli

pub fn build<'b, F>(rules: F) -> Builder where F: FnOnce<(&'b mut Builder,),()> 

Ten mówi, że build współpracuje z każdym żywotność rozmówca chce (np mógł wybrali 'b == 'static), ale to nieważne, bo nie ma konkretnego beton życia, która musi być wykorzystana : żywotność &mut builder wewnątrz funkcji. Używanie F: for<'a> ... w oprawie mówi, że F działa z dowolnym czasem życia 'a, więc kompilator widzi, że można go zastąpić w wersji &mut builder.

Jak wspomniałem powyżej, jest to naprawdę brzydka, nieumiejętna składnia. Są dwa kolejne sposoby, dzięki którym można zrobić o wiele ładniej. Po pierwsze, kanoniczny sposób używania cech zamknięcia to: () sugar: for<'a> FnOnce(&'a mut Builder) ->(), lub podobnie jak z resztą rdzy, ->() może zostać upuszczone: for<'a> FnOnce(&'a mut Builder). (. NB jest to cukier dla FnOnce<...>, ale tylko składnia słodzone będą stabilizowane przez oddziaływania z tych cech w 1.0.)

Następnie składnia paren ma trochę więcej regułę: automatycznie wstawia wcieleń, które działają jak for<'a> (konkretnie, podlega lifetime elision z każdym wprowadzonym czasem życia umieszczonym w for na cechie), więc tylko F: FnOnce(&mut Builder) jest równoważne F: for<'a> FnOnce(&'a mut Builder) i jest to zalecana wersja.

Stosując te poprawki do kojec przykład:

pub fn initialize_with_closure<F>(rules: F) -> uint where F: FnOnce(&mut uint) { 
    let mut i = 0; 
    rules(&mut i); 

    i 
} 

// equivalently 
pub fn initialize_with_closure_explicit<F>(rules: F) -> uint where F: for<'a> FnOnce(&'a mut uint) ->() { 
    let mut i = 0; 
    rules(&mut i); 

    i 
} 

pub fn main() { 
    initialize_with_closure(|i: &mut uint| *i = *i + 20); 
    initialize_with_closure_explicit(|i: &mut uint| *i = *i + 20); 
} 

playpen