2015-09-16 19 views
6

için uygulanmamıştır. Bir listeyi ikiye ayıran bir işlev oluşturmak istiyorum: belirli bir yüklemeyi karşılayan orijinal listenin öğelerini içeren bir liste ve diğeri olmayanları içeren bir liste .Sized, Fn

error[E0277]: the trait bound `for<'r> std::ops::Fn(&'r T) -> bool + 'static: std::marker::Sized` is not satisfied 
--> src/main.rs:1:47 
    | 
1 | fn split_filter<T: Clone + Sized>(a: &Vec<T>, f: Fn(&T) -> bool) -> (Vec<T>, Vec<T>) { 
    |            ^`for<'r> std::ops::Fn(&'r T) -> bool + 'static` does not have a constant size known at compile-time 
    | 
    = help: the trait `std::marker::Sized` is not implemented for `for<'r> std::ops::Fn(&'r T) -> bool + 'static` 
    = note: all local variables must have a statically known size 

error[E0308]: mismatched types 
    --> src/main.rs:17:39 
    | 
17 |  println!("{:?}", split_filter(&v, |&a| a % 3 == 0)); 
    |          ^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure 
    | 
    = note: expected type `for<'r> std::ops::Fn(&'r {integer}) -> bool + 'static` 
       found type `[[email protected]/main.rs:17:39: 17:54]` 

ikinci hata, bir kapatma bir Fn olmadığını ima etmek görünüyor:

fn split_filter<T: Clone + Sized>(a: &Vec<T>, f: Fn(&T) -> bool) -> (Vec<T>, Vec<T>) { 
    let i: Vec<T> = vec![]; 
    let e: Vec<T> = vec![]; 
    for u in a.iter().cloned() { 
     if f(&u) { 
      i.push(u) 
     } else { 
      e.push(u) 
     } 
    } 

    return (i, e); 
} 

fn main() { 
    let v = vec![10, 40, 30, 20, 60, 50]; 
    println!("{:?}", split_filter(&v, |&a| a % 3 == 0)); 
} 

Ancak, iki hata alıyorum: Aşağıda benim girişimidir. Çevrimiçi bir yerde bulduğum sözdizimini f: |&T| -> bool kullanmayı denedim, ancak bu, Rust'un en son sürümünde çalışmıyor gibi görünüyor.

İlk hataya gelince, TSized öğesinin işlevinin bilinen bir boyuta sahip olmasını sağlamasını umardım, ancak görünüşe göre değil.

+3

Gelecek okuyucular için, bu yöntem yineleme için zaten ['bölüm '] adı altında uygulanır (http://doc.rust-lang.org/std/iter/trait.Iterator.html#method.partition) . – Shepmaster

cevap

9

Resmi Rust kitabını özellikle the chapter on closures numaralı telefondan okumalısınız. İşlev beyanınız yanlış; f'un çıplak bir özellik türüne sahip olduğunu belirtiyorsunuz; bu mümkün değil; Bu tam olarak Sized ile ilgili hata hakkındadır. Bunun yerine genel tür parametresi kullanmalıdır: Ben de &[T] için &Vec<T> den a türünü değiştirmiş

fn split_filter<T: Clone, F>(a: &[T], f: F) -> (Vec<T>, Vec<T>) 
where 
    F: for<'a> Fn(&'a T) -> bool, 

; İlkini ikincisine tercih edeceğiniz bir durum yoktur. &Vec<T>, gerektiğinde otomatik olarak &[T]'a zorlanır. Bkz. Why is it discouraged to accept a reference to a String (&String) or Vec (&Vec) as a function argument? İkinci hata, işlev bildirimindeki hataya yakından bağlıdır; Orijinal işlev bildiriminiz çıplak bir özellik türü belirtiyor, ancak kapaklar bu türden yok, sadece işlev özelliğini uygular.

son programı aşağıdaki gibidir:

fn split_filter<T: Clone, F>(a: &[T], f: F) -> (Vec<T>, Vec<T>) 
where 
    F: Fn(&T) -> bool, 
{ 
    let mut i: Vec<T> = vec![]; 
    let mut e: Vec<T> = vec![]; 
    for u in a.iter().cloned() { 
     if f(&u) { 
      i.push(u); 
     } else { 
      e.push(u); 
     } 
    } 

    return (i, e); 
} 

fn main() { 
    let v = vec![10, 40, 30, 20, 60, 50]; 
    println!("{:?}", split_filter(&v, |&a| a % 3 == 0)); 
} 

playground Deneyin.

İlgili konular