यह सवाल सबसे निश्चित रूप से पहले उत्तर दिया गया है, लेकिन मैं एक नकली के रूप में यह बंद हो रहा नहीं कर रहा हूँ क्योंकि कोड यहाँ कुछ अलग है और मुझे लगता है कि यह महत्वपूर्ण है।
नोट कैसे आप अपने समारोह में परिभाषित किया गया:
fn combine(orig: &'a str) -> A<'a>
इसमें कहा गया है कि यह जिसका अंदर प्रदान की स्ट्रिंग के रूप में बिल्कुल के रूप में लंबे समय तक जीवित प्रकार A
का एक परिणाम प्रदान करेंगे। हालांकि, समारोह के शरीर इस घोषणा का उल्लंघन करती है:
let attr = &*(orig.to_string() + "suffix");
A {
some_attr: attr
}
यहाँ आप एक नईString
orig
से प्राप्त निर्माण, यह का एक टुकड़ा ले और A
अंदर वापस जाने के लिए प्रयास करें। हालांकि, orig.to_string() + "suffix"
के लिए बनाए गए निहित चर का जीवन इनपुट पैरामीटर के जीवनकाल से सख्ती से छोटा है। इसलिए, आपका प्रोग्राम अस्वीकार कर दिया गया है।
इस पर देखने के लिए एक और अधिक व्यावहारिक तरीका यह मानता है कि to_string()
द्वारा बनाई गई स्ट्रिंग और समन्वय को कहीं भी रहना है। हालांकि, आप केवल इसके उधारित टुकड़े को वापस कर देते हैं। इस प्रकार जब कार्य निकलता है, तो स्ट्रिंग नष्ट हो जाती है, और लौटा हुआ टुकड़ा अमान्य हो जाता है। यह वही स्थिति है जो जंग रोकती है।
इस आप कर सकते हैं पर काबू पाने के लिए या तो संग्रहीत करने के लिए एक String
A
अंदर:
pub struct A {
some_attr: String
}
या आप या तो एक टुकड़ा या एक स्वामित्व स्ट्रिंग स्टोर करने के लिए std::borrow::Cow
उपयोग कर सकते हैं:
pub struct A<'a> {
some_attr: Cow<'a, str>
}
पिछले मामले में अपने फ़ंक्शन इस तरह दिख सकता है:
fn combine(orig: &str) -> A<'static> {
let attr = orig.to_owned() + "suffix";
A {
some_attr: attr.into()
}
}
ध्यान दें कि क्योंकि आप फ़ंक्शन के अंदर स्ट्रिंग का निर्माण करते हैं, इसे Cow
के स्वामित्व वाले रूप के रूप में दर्शाया जाता है और इसलिए आप परिणामस्वरूप मान के लिए 'static
आजीवन पैरामीटर का उपयोग कर सकते हैं। इसे orig
पर लेना भी संभव है लेकिन ऐसा करने का कोई कारण नहीं है।
Cow
के साथ यह भी सीधे स्लाइस से बाहर आवंटन बिना A
के मूल्यों को बनाने के लिए संभव है:
fn new(orig: &str) -> A {
A { some_attr: orig.into() }
}
यहाँ A
के जीवनकाल पैरामीटर इनपुट स्ट्रिंग के जीवनकाल के लिए (जीवन इलिजन के माध्यम से) जोड़ दी जाएंगी टुकड़ा। इस मामले में Cow
के उधारित संस्करण का उपयोग किया जाता है, और कोई आवंटन नहीं किया जाता है।
भी ध्यान रखें कि यह to_owned()
या into()
String
रों को स्ट्रिंग स्लाइस कन्वर्ट करने के लिए है क्योंकि इन तरीकों को चलाने के लिए स्वरूपण कोड की आवश्यकता नहीं है और इसलिए वे अधिक कुशल हैं उपयोग करने के लिए बेहतर है।
आप इसे जीवन भर पर कैसे लौट सकते हैं जब आप इसे फ्लाई पर बना रहे हैं? सुनिश्चित नहीं है कि "Cow
" का स्वामित्व वाला संस्करण क्या है और क्यों यह 'static
संभव बनाता है।
pub enum Cow<'a, B> where B: 'a + ToOwned + ?Sized {
Borrowed(&'a B),
Owned(B::Owned),
}
यह जटिल लग रहा है, लेकिन यह तथ्य सरल है:
यहाँ Cow
की परिभाषा है। Cow
का एक उदाहरण या तो B
या किसी स्वामित्व वाले मान का संदर्भ हो सकता है जिसे B
से ToOwned
विशेषता के माध्यम से लिया जा सकता है। क्योंकि str
लागू करता ToOwned
जहां Owned
जुड़े प्रकार String
(ToOwned<Owned = String>
, जब यह enum str
के लिए विशेष है के रूप में लिखा करने के लिए बराबर होती है, यह इस तरह दिखता है:
pub enum Cow<'a, str> {
Borrowed(&'a str),
Owned(String)
}
इसलिए
, Cow<str>
या तो एक स्ट्रिंग टुकड़ा या एक स्वामित्व स्ट्रिंग का प्रतिनिधित्व कर सकते हैं - और जब तक Cow
वास्तव में क्लोन-ऑन-राइट कार्यक्षमता के लिए तरीके प्रदान करता है, यह बस के रूप में अक्सर एक मूल्य है जो या तो उधार लिया जा सकता या आदेश अतिरिक्त आवंटन से बचने के लिए स्वामित्व धारण करने के लिए प्रयोग किया जाता है। क्योंकि Cow<'a, B>
लागू करता Deref<Target = B>
, आप Cow<'a, B>
से &B
प्राप्त कर सकते हैं सरल रेबो के साथ रोइंग: x
Cow<str>
है, तो &*x
&str
है, चाहे x
के अंदर क्या है, स्वाभाविक रूप से, आप Cow
के दोनों प्रकारों से एक टुकड़ा निकाल सकते हैं।
आप देख सकते हैं कि Cow::Owned
संस्करण में इसके अंदर कोई संदर्भ नहीं है, केवल String
। इसलिए, Cow
का मान Owned
संस्करण का उपयोग करके बनाया गया है, आप किसी भी जीवनकाल को चुन सकते हैं (याद रखें, आजीवन पैरामीटर जेनेरिक टाइप पैरामीटर की तरह हैं; विशेष रूप से, यह कॉलर है जो उन्हें चुनने के लिए मिलता है) - वहां हैं इस पर कोई प्रतिबंध नहीं है। तो यह सबसे अच्छा जीवनकाल संभव के रूप में 'static
चुनने के लिए समझ में आता है।
क्या orig.to_owned
इस समारोह को कॉल करने वाले व्यक्ति से स्वामित्व हटा दें? ऐसा लगता है कि यह असुविधाजनक होगा।
to_owned()
विधि ToOwned
विशेषता के अंतर्गत आता है:
pub trait ToOwned {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
}
इस विशेषता Owned
String
के बराबर के साथ str
द्वारा कार्यान्वित किया जाता। to_owned()
विधि किसी भी मूल्य के स्वामित्व वाले संस्करण को लौटाती है जिसे इसे कहा जाता है। इस विशेष मामले में, यह String
&str
से बाहर बनाता है, प्रभावी ढंग से स्ट्रिंग स्लाइस की सामग्री को नए आवंटन में कॉपी करता है। इसलिए नहीं, to_owned()
स्वामित्व हस्तांतरण का संकेत नहीं देता है, ऐसा लगता है कि यह एक "स्मार्ट" क्लोन का तात्पर्य है।
जहां तक मेरा बता सकते हैं स्ट्रिंग Into<Vec<u8>>
नहीं बल्कि str
लागू करता है, तो कैसे हम 2 उदाहरण में into()
कॉल कर सकते हैं?
Into
विशेषता बहुत बहुमुखी है और इसे मानक पुस्तकालय में कई प्रकार के लिए लागू किया गया है। Into
आमतौर पर From
विशेषता के माध्यम से लागू किया जाता है: यदि T: From<U>
, तो U: Into<T>
। वहाँ मानक पुस्तकालय में From
के दो महत्वपूर्ण कार्यान्वयन हैं:
impl<'a> From<&'a str> for Cow<'a, str>
impl<'a> From<String> for Cow<'a, str>
ये कार्यान्वयन बहुत सरल हैं - वे केवल वापसी Cow::Borrowed(value)
अगर value
&str
और Cow::Owned(value)
है अगर value
String
है।
इसका मतलब है कि &'a str
और String
Into<Cow<'a, str>>
लागू, और इसलिए वे into()
विधि के साथ Cow
में बदला जा सकता। मेरे उदाहरण में यह बिल्कुल होता है - मैं into()
का उपयोग कर String
या &str
से Cow<str>
को परिवर्तित करने के लिए उपयोग कर रहा हूं। इस स्पष्ट रूपांतरण के बिना आपको बेमेल प्रकारों के बारे में एक त्रुटि मिलेगी।
धन्यवाद, यह काम करता है! लेकिन यहां बहुत कुछ है जो मुझे समझ में नहीं आता है, जब आप इसे फ्लाई पर बना रहे हैं तो आप जीवनकाल 'स्थिर' के 'ए' को कैसे वापस कर सकते हैं? सुनिश्चित नहीं है कि "गाय' के स्वामित्व वाले संस्करण" का अर्थ क्या है और यह क्यों 'स्थैतिक' संभव बनाता है। हम किसी भी बिंदु पर 'some_attr' को कभी भी संशोधित नहीं कर रहे हैं - क्या आमतौर पर लिखने की अनुमति देने के लिए "लिखने पर प्रतिलिपि" का बिंदु नहीं है? क्या 'orig.to_owned' इस फ़ंक्शन को कॉल करने वाले व्यक्ति से स्वामित्व हटा देता है? ऐसा लगता है कि यह असुविधाजनक होगा। जहां तक मैं 'स्ट्रिंग' लागू कर सकता हूं '>' लेकिन 'str' में नहीं, तो हम दूसरे उदाहरण में '()' को कैसे कॉल कर सकते हैं? –
wrongusername
वाह, यह बहुत सारे प्रश्न हैं! मैंने अपना जवाब अपडेट कर लिया है, उम्मीद है कि यह सहायक होगा :) –