मैंने संकलक को मेरा मार्गदर्शन करने के लिए उपयोगी पाया है:
fn to_words(text: &str) { // Note no return type
text.split(' ')
}
संकलन देता है:
error[E0308]: mismatched types
--> src/lib.rs:5:5
|
5 | text.split(' ')
| ^^^^^^^^^^^^^^^ expected (), found struct `std::str::Split`
|
= note: expected type `()`
found type `std::str::Split<'_, char>`
help: try adding a semicolon
|
5 | text.split(' ');
| ^
help: try adding a return type
|
3 | fn to_words(text: &str) -> std::str::Split<'_, char> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
संकलक के सुझाव और कॉपी-पेस्ट के बाद कि मेरी वापसी प्रकार के रूप में (थोड़ी सफाई के साथ):
use std::str;
fn to_words(text: &str) -> str::Split<'_, char> {
text.split(' ')
}
समस्या यह है कि आप एक विशेषता को वापस नहीं कर सकते Iterator
क्योंकि एक विशेषता का आकार नहीं है। इसका मतलब यह है कि रस्ट को पता नहीं है कि टाइप के लिए कितना स्थान आवंटित करना है। आप किसी स्थानीय चर का संदर्भ नहीं लौटा सकते हैं , इसलिए, लौटना &dyn Iterator
एक गैर स्टार्टर है।
इम्प्लांट का निशान
1.26 जंग के रूप में, आप उपयोग कर सकते हैं impl trait
:
fn to_words<'a>(text: &'a str) -> impl Iterator<Item = &'a str> {
text.split(' ')
}
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
इस पर प्रतिबंध हैं कि इसका उपयोग कैसे किया जा सकता है। आप केवल एक ही प्रकार (कोई शर्त नहीं!) लौटा सकते हैं और इसका उपयोग नि: शुल्क फ़ंक्शन या अंतर्निहित कार्यान्वयन पर किया जाना चाहिए।
बॉक्स्ड
अगर आपको थोड़ी सी दक्षता खोने का मन नहीं है, तो आप एक वापसी कर सकते हैं Box<dyn Iterator>
:
fn to_words<'a>(text: &'a str) -> Box<dyn Iterator<Item = &'a str> + 'a> {
Box::new(text.split(' '))
}
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
यह प्राथमिक विकल्प है जो गतिशील प्रेषण के लिए अनुमति देता है । यानी, कोड का सटीक कार्यान्वयन संकलन-समय के बजाय रन-टाइम पर तय किया जाता है। इसका मतलब है कि यह उन मामलों के लिए उपयुक्त है जहां आपको एक शर्त के आधार पर एक से अधिक ठोस प्रकार के पुनरावृत्ति करने की आवश्यकता होती है।
नया प्रकार
use std::str;
struct Wrapper<'a>(str::Split<'a, char>);
impl<'a> Iterator for Wrapper<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
fn to_words(text: &str) -> Wrapper<'_> {
Wrapper(text.split(' '))
}
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
उपनाम लिखें
जैसा कि रीम ने बताया
use std::str;
type MyIter<'a> = str::Split<'a, char>;
fn to_words(text: &str) -> MyIter<'_> {
text.split(' ')
}
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
बंदों से निपटना
जब impl Trait
उपयोग के लिए उपलब्ध नहीं है, तो बंद करने से चीजें अधिक जटिल हो जाती हैं। क्लोज़र अनाम प्रकार बनाते हैं और इन्हें रिटर्न प्रकार में नाम नहीं दिया जा सकता है:
fn odd_numbers() -> () {
(0..100).filter(|&v| v % 2 != 0)
}
found type `std::iter::Filter<std::ops::Range<{integer}>, [closure@src/lib.rs:4:21: 4:36]>`
कुछ मामलों में, इन क्लोजर को फ़ंक्शंस से बदला जा सकता है, जिन्हें नाम दिया जा सकता है:
fn odd_numbers() -> () {
fn f(&v: &i32) -> bool {
v % 2 != 0
}
(0..100).filter(f as fn(v: &i32) -> bool)
}
found type `std::iter::Filter<std::ops::Range<i32>, for<'r> fn(&'r i32) -> bool>`
और उपरोक्त सलाह का पालन करें:
use std::{iter::Filter, ops::Range};
type Odds = Filter<Range<i32>, fn(&i32) -> bool>;
fn odd_numbers() -> Odds {
fn f(&v: &i32) -> bool {
v % 2 != 0
}
(0..100).filter(f as fn(v: &i32) -> bool)
}
सशर्त से निपटना
यदि आपको सशर्त रूप से एक पुनरावृत्ति चुनने की आवश्यकता है, तो कई संभावित पुनरावृत्तियों में से एक पर सशर्त रूप से पुनरावृति देखें ।