2014-09-27 20 views
7

Ben Rust öğreniyorum ve ben stdin gelen tamsayı dizisi okumak için aşağıdaki kodu yazdım:bir `değer ömrünü artırmak için bağlayıcı let`

use std::io; 
fn main() { 
    for line in io::stdin().lines() { 
     let xs:Vec<int> = line.unwrap().as_slice().trim().split(' ') 
       .map(|s|from_str::<int>(s).unwrap()).collect(); 
     println!("{}", xs); 
    } 
} 

Ancak bu, iyi çalıştı hissettim let xs çizgi biraz uzun, o yüzden ikiye bölmek:

fn main() { 
    for line in io::stdin().lines() { 
     let ss = line.unwrap().as_slice().trim().split(' '); 
     let xs:Vec<int> = ss.map(|s|from_str::<int>(s).unwrap()).collect(); 
     println!("{}", xs); 
    } 
} 

Bu işe yaramadı! Rust, aşağıdaki hatayı yanıtladı:

hello.rs:4:12: 4:25 error: borrowed value does not live long enough 
hello.rs:4  let ss = line.unwrap().as_slice().trim().split(' '); 
         ^~~~~~~~~~~~~ 
hello.rs:3:34: 7:3 note: reference must be valid for the block at 3:33... 
hello.rs:3 for line in io::stdin().lines() { 
hello.rs:4  let ss = line.unwrap().as_slice().trim().split(' '); 
hello.rs:5  let xs:Vec<int> = ss.map(|s|from_str::<int>(s).unwrap()).collect(); 
hello.rs:6  println!("{}", xs); 
hello.rs:7 } 
hello.rs:4:3: 4:54 note: ...but borrowed value is only valid for the statement at 4:2; consider using a `let` binding to increase its lifetime 
hello.rs:4  let ss = line.unwrap().as_slice().trim().split(' '); 
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
error: aborting due to previous error 

Bu beni şaşırtıyor. Yeterince uzun yaşamadığı line veya ss mu? Ve ömürlerini arttırmak için izin vermeyi nasıl kullanabilirim? Zaten bir izin kullandım mı sandım?

Web için çözümler arıyor ve Lifetime guide aracılığıyla okudum, ancak yine de tam olarak anlayamıyorum. Herkes bana bir ipucu verebilir mi?

cevap

9

İkinci sürümünüzde, ss'un türü CharSplits<'a, char>'dur. Türdeki ömür boyu parametresi, nesnenin bir referans içerdiğini belirtir. Ödevin geçerli olması için, referansın bu ifadeden sonra var olan bir nesneyi göstermesi gerekir. Bununla birlikte unwrap(), line; Başka bir deyişle, Ok varyantının verilerini Result nesnesinden dışarı taşır. Bu nedenle, başvuru, orijinal line'un yerine değil, geçici bir nesneye işaret eder.

İlk sürümde, map numaralı çağrıya rağmen, uzun ifadenin sonuna kadar geçici olanı kullanırsınız. Yani `line`` xs` çizgiyi izin kapsam dışında olduğunu söylediğini

use std::io; 

fn main() { 
    for line in io::stdin().lines() { 
     let line = line.unwrap(); 
     let ss = line.as_slice().trim().split(' '); 
     let xs: Vec<int> = ss.map(|s|from_str::<int>(s).unwrap()).collect(); 
     println!("{}", xs); 
    } 
} 
+0

Sadece doğru bir şekilde anladığımdan emin olmak için, 'CharSplits' satırın içindeki değere referans verir. Ama aslında, 's' satırının bittiği anda atılan' Ok 'dan alınan bir kopyaya atıfta bulunuyor. Tüm değerleri blokun sonuna kadar canlı tutmak yerine? –

+0

Evet. Geçici değerler sadece o değeri üreten ifadenin bulunduğu deyim için geçerlidir. –

+0

"Satır" ın içine işaret etmemesi bir hafıza kaybı değil mi? –

3

Bu, unwrap() numaralı çağrı hakkındadır, içerilen nesneyi alır, ancak bu başvuru, kapsayıcı nesneyi, bir sonraki satırda kapsam dışına çıkacak şekilde aşmalıdır (buna yerel bir bağ yoktur).

sen temizleyici kodu almak istiyorsanız

, bunu yazmak için çok yaygın bir yoludur: Değilse, bağlayıcı "unwraped" sonuç oluşturmak ve kullanabilirsiniz

use std::io; 

fn main() { 
    for line in io::stdin().lines() { 
     let xs:Vec<int> = 
      line 
      .unwrap() 
      .as_slice() 
      .trim() 
      .split(' ') 
      .map(
       |s|from_str::<int>(s).unwrap() 
      ) 
      .collect(); 
     println!("{}", xs); 
    } 
} 

.

Yardım edin.

+0

ama: ikinci versiyonunu düzeltmek için, yeterince uzun yaşayan değerini tutmak için unwrap() sonucunu bağlamak gerekir Aynı blokta olsalar bile, ss' satırında değil? –

+1

Bu, kapsam dışında olan line.unwrap() 'sonucudur. – snf

+0

Teşekkür ederim Sanırım anlamaya başladım. –

İlgili konular