2016-12-10 7 views
6

मैं जंग के लिए अपेक्षाकृत नया हूं, और मैं iterators के बारे में जानने की कोशिश कर रहा हूँ। जिस विशिष्ट समस्या पर मैं काम कर रहा हूं वह एक इटरेटर है जो त्रिभुज संख्या उत्पन्न करता है (त्रिकोण संख्या 1, 3, 6, 10, 15 जहां 1 = 1, 3 = 1 + 2, 6 = 1 + 2 + 3 आदि) होती है। मेरे द्वारा बनाए गए इस की मूल बातें, यहाँ दिखाया गया है:क्या कस्टम इटरेटर :: रस्ट में योग लागू करना संभव है?

pub struct Triangle { 
    cur: u32, 
    n: u32, 
    m: u32, 
} 

impl Iterator for Triangle { 
    type Item = u32; 

    fn next(&mut self) -> Option<u32> { 
     if self.n == self.m { 
      return None; 
     } 
     self.n = self.n + 1; 
     self.cur = self.cur + self.n; 

     Some(self.cur) 
    } 
} 

इस का एक त्वरित runnable उदाहरण

let t = Triangle { cur: 0, n: 0, m: 10 }; 
let s: u32 = t.sum(); 
println!("{}", s); // prints 220 

है यह इटरेटर उस प्रकार u32 रिटर्न के लिए एक कस्टम योग समारोह बनाने के लिए संभव है। मैं डिफ़ॉल्ट इटरेटर और योग कार्यों के साथ ऐसा करने में सक्षम होने की उम्मीद कर रहा था, और मुझे अपना खुद का विशेष कार्य नहीं करना है।

मैं इस में एक देखो पड़ा है, और मैं क्या करने में सक्षम हो उम्मीद कर रही थी

impl Sum<u32> for u32 { 
    fn sum<I>(iter: I) -> Self where I: Triangle { 
     let nsum = (self.n * (self.n + 1) * (self.n + 2))/6; 
     let msum = (self.m * (self.m + 1) * (self.m + 2))/6; 
     msum - nsum 
    } 
} 

है, लेकिन यह काम नहीं करता। त्रुटि है कि मैं इस के साथ मिल

error[E0404]: `Triangle` is not a trait 
    --> src/sequences.rs:61:41 
    | 
61 |  fn sum<I>(iter: I) -> Self where I: Triangle { 
    |           ^^^^^^^^ not a trait 

मैं इसे चाहता है की तरह Iterator करने के लिए Triangle से यह बदल सकता है, लेकिन है कि मुझे Triangle struct के m और n मूल्यों तक पहुँचने से रोका जा सके। अगर कोई मुझे बता सकता है कि यह कैसे करना है, या यदि यह असंभव है, तो यह बहुत अच्छा होगा। मुझे पता है कि मैं कुछ और कहलाता हूं, जैसे my_sum(), लेकिन मैं इसे एक पुनरावर्तक के संदर्भ में करने में सक्षम होने की उम्मीद कर रहा था।

+1

और एक [एमसीवीई] का उत्पादन - 'नम' मानक जंग के हिस्से के रूप में एक विशेषता नहीं है, तो हम कैसे जानते हैं कि यह क्या कर सकता है? – Shepmaster

+0

शायद [मैं एक ऐसे गुण को कैसे कार्यान्वित करूं जो मेरे पास नहीं है, मेरे पास नहीं है?] (Http://stackoverflow.com/q/25413201/155423) आपको जो कुछ जानने की आवश्यकता है उसे समझाएगा? – Shepmaster

+0

@ शेमपस्टर मुझे लगता है कि यह वास्तव में इसके बारे में नहीं है, लेकिन 'त्रिकोण 'इटरेटर के लिए एक कुशल ओ (1) कार्यान्वयन प्रदान करने के बारे में है। मुझे लगता है कि 'Iterator :: sum()' ओवरराइडिंग समाधान है ... शायद। –

उत्तर

4

आप Sum के मौजूदा कार्यान्वयन को विशेषज्ञ नहीं कर सकते हैं, लेकिन आप अपने पुनरावर्तक में Iterator::sum विशेषज्ञ कर सकते हैं! हालांकि, यह थोड़ा मुश्किल है, क्योंकि इसके रिटर्न प्रकार सामान्य हैं।

use std::iter::{self, Sum}; 

impl Iterator for Triangle { 
    // existing members are unchanged 

    fn sum<S>(self) -> S where S: Sum<Self::Item> { 
     let nsum = (self.n * (self.n + 1) * (self.n + 2))/6; 
     let msum = (self.m * (self.m + 1) * (self.m + 2))/6; 
     S::sum(iter::once(msum - nsum)) 
    } 
} 

हम (जैसे u32 के रूप में) एक निश्चित प्रकार वापस नहीं लौट सकते, कि के रूप में अनुबंध Iterator विशेषता द्वारा परिभाषित का सम्मान नहीं होता। हम सभी को वापसी प्रकार S के बारे में पता है कि यह Sum<Self::Item> लागू करता है। Sum में एक ही विधि है, sum, जो Self देता है, इसलिए हम इसे S टाइप करने के लिए उपयोग कर सकते हैं। विधि एक पुनरावर्तक की अपेक्षा करता है; हम इसे Once खिलाते हैं, "एक पुनरावर्तक जो एक बार तत्व उत्पन्न करता है"। चूंकि इटेटरेटर निश्चित समय को फिर से चालू करेगा, इसलिए हम निश्चित संख्या में संचालन करने के लिए sum की उम्मीद कर सकते हैं।

जब आप को रिलीज़ मोड में कार्यक्रम संकलन और Su32 है, पूरी sum कॉल दूर अनुकूलित है, और समारोह msum - nsum सीधे देता है।

+0

आह, मैं बहुत करीब था, लेकिन यह नहीं पता था कि 'टी' से' एस' तक कैसे जाना है। यह एक बहुत अच्छा समाधान है! – Shepmaster

संबंधित मुद्दे