2014-10-13 9 views
6

मुझे एक चरित्र धारा में आगे बढ़ने में दिलचस्पी है। मेरी समझ के लिए, Peekable जाने का रास्ता होगा। मैं नहीं कर सकता इसका उपयोग कैसे करें इसका पता लगाएं।जंग की चोटी का उपयोग कैसे करें?

प्रथम प्रयास:

fn trawl<I, E>(pk: &mut I) where I: std::iter::Peekable<Result<char, E>> { 
    loop { 
     let cur = pk.next(); 
     let nxt = pk.peek(); 
     match (cur, nxt) { 
      (Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()), 
      _ =>(), 
     } 
    } 
} 

fn main() { 
    trawl(&mut std::io::stdio::stdin().chars()); 
} 

इस के साथ

> rustc /tmp/main.rs 
/tmp/main.rs:1:37: 1:73 error: `std::iter::Peekable` is not a trait 
/tmp/main.rs:1 fn trawl<I, E>(pk: &mut I) where I: std::iter::Peekable<Result<char, E>> { 
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
error: aborting due to previous error 

ठीक है, पर्याप्त उचित संकलित करने के लिए विफल रहता है। मैं पूरी तरह से लक्षण समझ में नहीं आता अभी तक तो मैं में एक इटरेटर पारित करने के लिए और फिर एक peekable संस्करण बनाने की कोशिश: साथ

fn trawl<I, E>(it: &mut I) where I: Iterator<Result<char, E>> { 
    let mut pk = it.peekable(); 
    loop { 
     let cur = pk.next(); 
     let nxt = pk.peek(); 
     match (cur, nxt) { 
      (Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()), 
      _ =>(), 
     } 
    } 
} 

fn main() { 
    trawl(&mut std::io::stdio::stdin().chars().peekable()); 
} 

यह विफल रहता है

> rustc /tmp/main.rs 
/tmp/main.rs:2:18: 2:20 error: cannot move out of dereference of `&mut`-pointer 
/tmp/main.rs:2  let mut pk = it.peekable(); 
           ^~ 
/tmp/main.rs:7:65: 7:70 error: cannot move out of dereference of `&`-pointer 
/tmp/main.rs:7    (Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()), 
                       ^~~~~ 
note: in expansion of format_args! 
<std macros>:2:23: 2:77 note: expansion site 
<std macros>:1:1: 3:2 note: in expansion of println! 
/tmp/main.rs:7:39: 7:77 note: expansion site 
error: aborting due to 2 previous errors 

कोई समझा सकते हैं:

  • क्यों पेकटेबल एक विशेषता होने की कमी के लिए फ़ंक्शन प्रकार में दिखाई नहीं दे सका,
  • कंपाइलर का क्या मतलब है जब 'कहां से बाहर निकलना' और
  • मैं या तो दोनों को कैसे हल कर सकता हूं?

एक तीसरे संस्करण

fn trawl<I, E>(mut it: I) where I: Iterator<Result<char, E>> { 
    let mut pk = it.peekable(); 
    loop { 
     let cur = pk.next(); 
     let nxt = pk.peek(); 
     match (cur, nxt) { 
      (Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()), 
      // (Some(i),) => println!("{}", i.ok()), 
      _ =>(), 
     } 
    } 
} 

fn main() { 
    trawl(std::io::stdio::stdin().chars().peekable()); 
} 

यह विफल रहता है के साथ: मैं

> rustc /tmp/main.rs 
/tmp/main.rs:7:65: 7:70 error: cannot move out of dereference of `&`-pointer 
/tmp/main.rs:7    (Some(i), Some(nxt_i)) => println!("{} {}", i.ok(), nxt_i.ok()), 
                       ^~~~~ 
note: in expansion of format_args! 
<std macros>:2:23: 2:77 note: expansion site 
<std macros>:1:1: 3:2 note: in expansion of println! 
/tmp/main.rs:7:39: 7:77 note: expansion site 
error: aborting due to previous error 

समझने के लिए जंग मेरे लिए कह रहा है यहाँ, कैसे Iterator.next एक अलग होता है असफल Peekable.peek से वापसी प्रकार।

उत्तर

5

Peekable एक विशेषता नहीं है और इस प्रकार बाध्य के रूप में उपयोग नहीं किया जा सकता है, जो सुझाव देगा कि इसका मतलब कई प्रकारों में से एक हो सकता है। यह एक एकल, विशिष्ट, ठोस प्रकार, struct Peekable<A, T> है।जैसा कि आपने देखा है, यह एक इटरेटर पर peekable() विधि को कॉल करके बनाया गया है, जो इसे किसी चीज में बदल देता है जो देखने योग्य है।

यहाँ कैसे आप इसका उपयोग करता है, तो आप सिर्फ एक इटरेटर ले जाना चाहते थे है:

fn trawl<I, E>(iter: I) where I: Iterator<Result<char, E>> { 
    let pk = pk.peekable(); 
    … 
} 

भी कि peekable() विधि मूल्य द्वारा स्वयं लेता नोट; आप वहां एक इटरेटर के लिए एक परिवर्तनीय संदर्भ नहीं ले सकते हैं।

विकल्प है जो है आपके लिए क्या लक्ष्य कर रहे थे लेकिन जो मैं करने की दिशा में आम तौर पर कम इच्छुक हो सकता है, होता peekable होने के लिए तर्क की आवश्यकता के लिए हो सकता है, फोन करने वाले पर बोझ डालने, जैसा कि आप था:

fn trawl<I, E>(pk: Peekable<E, I>) where I: Iterator<Result<char, E>> { 
    … 
} 
+0

मुझे पता नहीं था कि stdin के बारे में। धन्यवाद। – troutwine

+2

भावी पाठकों के लिए नोट: जब यह उत्तर लिखा गया था, ['stdin()' सुरक्षित रूप से उपयोग करना मुश्किल था] (https://github.com/rust-lang/rust/issues/14434)। यह अब मामला नहीं है, हालांकि, दिसंबर 2014 में यह मुद्दा तय किया गया था। – kiwidrew

4

Peekable वास्तव में एक संरचना है, न कि एक विशेषता है। यदि आप एक Peekable ले जाना चाहते थे, तो आप इस तरह अपने कार्य निर्धारित कर सकते हैं:

fn trawl<E, I>(it: Peekable<I>) where I: Iterator<Result<char, E>> { 
    ... 
} 

आपकी दूसरी कार्यान्वयन संकलित करने के लिए क्योंकि peekself मूल्य से लेता है विफल हो रहा है (यानी यह खपत इटरेटर, एक नया लौटने) , इसलिए आप इसे &mut संदर्भ के माध्यम से कॉल नहीं कर सकते हैं। अधिकांश कोड बस मूल्य के बजाय संदर्भ द्वारा इटरेटर लेता है:

fn trawl<E, I>(it: I) where I: Iterator<Result<char, E>> { 
    let it = it.peekable(); 
    ... 
} 

आप trawl की तरह एक समारोह में इटरेटर ले जाने के लिए नहीं करना चाहते हैं, तो आप by_ref() विधि एक नया इटरेटर उस पर रखती है बनाने के लिए उपयोग कर सकते हैं एक &mut संदर्भ:

let mut my_iterator = /* whatever */; 
trawl(my_iterator.by_ref()); 
// my_iterator is still usable here 

जहां तक ​​शैली से चला जाता है के रूप में, मैं कहूँगा कि दूसरा रूप पहले लीक क्या मूल रूप से एक कार्यान्वयन विस्तार के रूप में, जाने के लिए बेहतर तरीका है।

+0

यदि इटरेटर को 'trawl' के मान में पारित किया जाता है, तो फिर एक व्यक्ति अपनी सामग्री के माध्यम से फिर से कैसे घुमाएगा, क्योंकि यह इटरेटर को बदलता है? मैं इस बारे में उलझन में हूं कि यहां क्या करना सही है - आत्मा में - मैं दूसरे कार्यान्वयन के साथ क्या कर रहा था। – troutwine

+0

यदि इटरेटर को 'trawl' के मान से पारित किया जाता है, तो फ़ंक्शन का स्वामित्व होता है, और जो कुछ भी इसके साथ चाहता है वह कर सकता है। आप 'fn trawl (it: I) कर सकते हैं {इसे mut = it; ...} 'पुनरावृत्त पर पुनरावृत्ति की अनुमति देने के लिए। इसके लिए एक शॉर्टेंड भी है जो अर्थशास्त्र में बिल्कुल समान है: 'fn trawl (mut it: I) {...} '। – sfackler