2015-01-07 11 views
9
kodu yeniden nasıl

yeni birisi kutusuz kapanışları ile Bu kod parçasını yeniden yazmak için bana yardımcı olabilir:yeni kutusuz kapanışları

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

    builder 
} 

Böyle yazmaya çalıştım, ama bir ömür boyu hata var:

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,),()> { 
                        ^~~~~~~~~~~~ 

Hangi ömür boyu belirtmem gerekiyor? Simplified example in the sandbox.

+1

Yakın seçmen: neden bu offtopic? – huon

cevap

12

Bu, özellikle daha yüksek sıra ömürleri olan higher rank trait bounds gerektirir. Tam tekdüzen sözdizimi F: for<'a> FnOnce<(&'a mut Builder,),()> olur.

Bir ömür boyu kullanımda işlev kullanılamaz, örn. Biz

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

olsaydı bu build eser ne olursa olsun ömür boyu birlikte arayanın istediği söylüyor (örneğin onlar 'b == 'static seçti olabilir), ancak kullanılması gerekirse, belirli bir beton ömrü olduğundan bu, geçersiz : fonksiyonun içinde &mut builder'un ömrü. F: for<'a> ... bir sınırda kullanıldığında F herhangi bir ömür boyu 'a ile çalıştığı için derleyici &mut builder'dan birinin yerine yasal olduğunu görür.

Yukarıda belirtildiği gibi, bu gerçekten çirkin bir çift sözdizimi. Bunun daha güzel hale getirilebilmesi için birbirini izleyen iki yol var. İlk olarak, kapanma özelliklerini kullanmanın kuralsal yolu () şekeri: for<'a> FnOnce(&'a mut Builder) ->(), ya da Rust'un geri kalanıyla olduğu gibi, ->() atılabilir: for<'a> FnOnce(&'a mut Builder). (. NB bu FnOnce<...> için sadece şeker, ama sadece şekerli sözdizimi 1.0'da bu özelliklerin etkileşim için stabilize edilir.)

Sonra parantez sözdizimi biraz ekstra kuralı vardır: otomatik for<'a> gibi hareket ömür ekler (özellikle, for öğesinin içine yerleştirilmiş herhangi bir ömür boyu ile lifetime elision geçer), bu nedenle yalnızca F: FnOnce(&mut Builder)F: for<'a> FnOnce(&'a mut Builder) eşdeğerdir ve önerilen sürümdür.

sizin playpen örneğe bu düzeltmeleri uygulamak:

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

İlgili konular