2015-06-04 14 views
8

Her öğeyi oluşturan ve düz bir Vec (her sırayla birleştirilen) olarak depolayan bir functor'dan 2 boyutlu bir matris yapmaya çalışıyorum.Yuvalanmış haritada kapaklar nasıl kullanılır?

Her satırı oluşturmak ve birleştirmek için yuvalanmış bir harita (aslında bir flat_map ve yuvalanmış bir harita) kullandım. Here is what I tried:

fn make<T,F>(n: usize, m: usize, f: F) -> Vec<T> 
    where F: Fn(usize,usize) -> T 
{ 
    (0..m).flat_map(|y| (0..n).map(|x| f(x,y))).collect() 
} 

fn main() { 
    let v = make(5,5, |x,y| x+y); 

    println!("{:?}", v); 
} 

Ne yazık ki, (her zamanki 'yeterince uzun yaşamaz') derleme sırasında bir hata alıyorum. İç içe geçmiş haritalarda kapaklar nasıl kullanılır?

<anon>:4:36: 4:46 error: `y` does not live long enough 
<anon>:4  (0..m).flat_map(|y| (0..n).map(|x| f(x,y))).collect() 
              ^~~~~~~~~~ 
<anon>:4:5: 4:58 note: reference must be valid for the method call at 4:4... 
<anon>:4  (0..m).flat_map(|y| (0..n).map(|x| f(x,y))).collect() 
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
<anon>:4:25: 4:47 note: ...but borrowed value is only valid for the scope of parameters for function at 4:24 
<anon>:4  (0..m).flat_map(|y| (0..n).map(|x| f(x,y))).collect() 
           ^~~~~~~~~~~~~~~~~~~~~~ 

(Ben bu konuda by using a single map on 0..n*m çalıştı, ama hala cevap ilgileniyorum.)

Senin durumunda
+0

Belki bir http://stackoverflow.com/q/28521637/155423 kopyası mı? – Shepmaster

+0

Y beri umuyorum: usize Kopya-mümkün oldu, bu iç kapatma tarafından değer tarafından alınabilir, böylece herhangi bir borçlanma ihtiyacını ortadan kaldırarak ... – Gyscos

+0

Katılıyorum ve burada bir hata olduğunu biraz şaşırdım all - Bu 'FnMut' ile ilgili bir his var. Aynı zamanda gerçek bir hata da olabilir. Yağmurlama '.clone()' da tüm değişkenler problemi çözmediği gibi ben de düşündüm. – Shepmaster

cevap

7

iç kapatma |x| f(x,y) çevresini (y ve f alan bir borçlanma kapatma vardır) referans olarak.

.flat_map(..) yolunda çalışır, dış kapsamda olmayan y referansını korumanızı yasaklar.

(0..m).flat_map(|y| (0..n).map(move |x| f(x,y))).collect() 

Ancak şimdi başka bir sorun ortaya çıkar: Böylece biz kapatma Copy bir usize olmak y için bir sorun değil değerine göre kendi çevresini almak olması gerekir

<anon>:5:41: 5:51 error: cannot move out of captured outer variable in an `FnMut` closure 
<anon>:5  (0..m).flat_map(|y| (0..n).map(move |x| f(x,y))).collect() 
               ^~~~~~~~~~ 

Burada, pascık mutlu değil: f'u da kapatmaya çalışıyoruz, ki bu kesinlikle mümkün değil (m1 değilse, ancak derleyici bunu bilemez).

Ama f biz de açıkça buna bir & referansı geçebileceği anlamına gelen bir Fn(usize,usize) -> T, ve & referanslar Copy şunlardır: Bu durumda

fn make<T,F>(n: usize, m: usize, f: F) -> Vec<T> 
    where F: Fn(usize,usize) -> T 
{ 
    let f_ref = &f; 
    (0..m).flat_map(|y| (0..n).map(move |x| f_ref(x,y))).collect() 
} 

, kapatma değerine göre çevresini alır ve Bu ortam, her ikisi de Copy olmak üzere y ve f_ref, her şey yolunda oluşur.

+2

Ayrıca "fn make (n: usize, m: usize, ref f: F) -> Vec " yazıp, kapanışa bir atıfta bulunabilirsiniz. –

+0

Mükemmel! İkinci hata ile kafam karışmıştı, bunun hakkında konuştuğunun farkında değildim ... @ A.B .: Nice! Fonksiyon argümanlarındaki kalıpları unutmaya devam ediyorum. – Gyscos