2015-07-14 7 views
8

मैं जंग में बंद होने के लिए जीवनभर घोषित करना चाहता हूं, लेकिन मुझे आजीवन घोषणा जोड़ने का कोई तरीका नहीं मिल रहा है।एक बंद करने के लिए जीवन भर घोषित करने के लिए

यह अब के लिए मेरे बंद है:

let nt = |t: &'a mut SplitWhitespace| t.next().ok_or(missing_token(line_number)); 

Complete sample code on the playground

इस बंद होने के लिए मैं जीवनकाल 'a कैसे घोषित कर सकता हूं?

+0

इसे प्रबंधित नहीं कर सकता है। बेशक 'एफएन' काम' एफएन एनटी <'a> (टी: और 'एक म्यूट स्प्लिट व्हाइटस्पेस, लाइन_नंबर: उपयोग) -> परिणाम <&' एक स्ट्र, पार्सर एरर> { t.next()। Ok_or (missing_token (line_number)) } ' – tafia

+0

संबंधित: http://stackoverflow.com/questions/29714934/how-can-i-specify-a-lifetime-for-closure-arguments –

उत्तर

7

&mut SplitWhitespace वास्तव में &'b mut SplitWhitespace<'a> है। यहां प्रासंगिक जीवनकाल 'a है, क्योंकि यह निर्दिष्ट करता है कि स्ट्रिंग स्लाइस कितनी देर तक next लाइव लौटाती है। चूंकि आपने तर्क पर split_whitespace फ़ंक्शन लागू किया है, इसलिए आपको को उसी जीवनकाल में सेट करने की आवश्यकता है जो line तर्क है।

तो पहले कदम के रूप में आप line लिए एक जीवन भर जोड़ें:

fn process_string<'a>(line: &'a str, line_number: usize) -> Result<(), ParserError> { 

और फिर आप अपने बंद में टाइप करने के लिए जीवन भर जोड़ें:

let nt = |t: &mut SplitWhitespace<'a>| t.next().ok_or(missing_token(line_number)); 

ध्यान दें कि जब यह आपके सवाल का जवाब , आपकी समस्या का सही समाधान @A.B.'s solution है।

6

मैं आपके सवाल का जवाब देने के लिए कैसे पता नहीं है, लेकिन वहाँ समस्या को हल करने के दो तरीके हैं:

सबसे आसान एक बंद इटरेटर संदर्भ सीधे जाने के लिए है।

{ 
    let mut nt = || tokens.next().ok_or(missing_token(line_number)); 
    // call the closure as many times as you need to 
} 
    // At this point `tokens` will be usable again. 

आप वास्तव में बाद में tokens साथ कुछ भी करने की जरूरत नहीं है, बस कार्य करें:

let mut nt = || tokens.next().ok_or(missing_token(line_number)); 

अन्य समाधान एक समारोह है कि emulates क्या बंद कर रहा है लिख सकते हैं और बजाय फोन है कि करने के लिए है ।

+0

यह समस्या का उत्तर देता है, प्रश्न नहीं;), लेकिन @ पीटरसमेट शायद [एक्सवाई-समस्या] से पीड़ित है (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) –

+1

@ker शायद थोड़ा सा। मैं दोनों एक अच्छा और बेवकूफ समाधान चाहते हैं और समझते हैं कि क्यों कुछ काम करता है या नहीं। मेरे लिए यह इस समय लगता है कि अगर स्पष्ट जीवनकाल का उपयोग करने के बीच कोई विकल्प नहीं है (उदा। स्कॉप्स), तो स्पष्ट समय के बिना संस्करण का उपयोग करने के लिए सबसे अच्छा समय है –

1

जैसे कि मूल pointed out by DK., तो आप एक बंद के तर्कों के लिए अतिरिक्त बाधाओं लागू करते हैं और मूल्यों वापस जाने के लिए एक समारोह का उपयोग कर सकते हैं:

fn constrain<F>(f: F) -> F 
where 
    F: for<'a> Fn(&'a mut SplitWhitespace) 
     -> Result<&'a str, ParserError>, 
{ 
    f 
} 

यह आपको where खंड के पूर्ण क्षमताओं देता है; इस मामले में आप उच्च-रैंकिंग विशेषता सीमा (for <...>) का उपयोग यह कहने के लिए कर सकते हैं कि बंद करने के लिए उसी जीवनकाल के संदर्भ को तर्क के रूप में संदर्भित करना होगा।

let nt = constrain(|t| t.next().ok_or(missing_token(line_number))); 

अंत में, इस limitations in Rust's type inference के कारण होता है। विशेष रूप से, यदि किसी फ़ंक्शन को तुरंत उपयोग किए जाने वाले फ़ंक्शन पर पास किया जाता है, तो संकलक अनुमान लगा सकता है कि तर्क और वापसी प्रकार क्या हैं। दुर्भाग्यवश, जब इसे उपयोग करने से पहले एक चर में संग्रहीत किया जाता है, तो संकलक समान स्तर का अनुमान नहीं करता है।

यह कामकाज काम करता है क्योंकि यह तुरंत किसी फ़ंक्शन को बंद कर देता है, जो प्रकारों और आजीवन संदर्भों को कम करता है।

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