2015-05-06 5 views
5

कुछ घटना स्रोत की कल्पना करो, जो एक enum के रूप में प्रतिनिधित्व घटनाओं का उत्पादन करता है। बेशक, सबसे अच्छा दक्षता के लिए, इस निर्माता शून्य-प्रतिलिपि, है यानी वह अपने आंतरिक बफ़र्स के लिए संदर्भ देता है:उधार प्रकार को उधार प्रकार को संदर्भ के लिए क्यों आवश्यकता होती है?

enum Variant<'a> { 
    Nothing, 
    SomeInt(u64), 
    SomeBytes(&'a [u8]) 
} 

impl Producer { 
    fn next(&'a mut self) -> Variant<'a> { ... } 
} 

यह उपभोक्ताओं कि अग्रदर्शी या बैक ट्रैकिंग की आवश्यकता नहीं है के लिए पूरी तरह से ठीक है, लेकिन कभी कभी एक घटनाओं के कुछ अनुक्रम को बचाने की जरूरत है। इस प्रकार, हमारे Variant प्रकार एक सामान्य हो जाता है:

enum Variant<BytesT> { 
    Nothing, 
    SomeInt(u64), 
    SomeBytes(BytesT) 
} 

type OwnedVariant = Variant<Vec<u8>>; 
type BorrowedVariant<'a> = Variant<&'a [u8]>; 

यहाँ, हम "मालिक-संदर्भ" संबंध है, जो जोड़े Vec<T> के समान है के साथ दो प्रकार के साथ अंत - &[T], String - &str। डॉक्स builtin लक्षण Borrow और ToOwned जो सिर्फ क्या एक सूक्ष्म अति सूक्ष्म अंतर के अलावा आवश्यक है प्रदान करते हैं सुझाव देते हैं:

trait Borrow<Borrowed: ?Sized> { 
    fn borrow(&self) -> &Borrowed; 
    // this: -----------^ 
} 

pub trait ToOwned { 
    type Owned: Borrow<Self>; 
    fn to_owned(&self) -> Self::Owned; 
} 

borrow का परिणाम कुछ, जो स्पष्ट रूप से BorrowedVariant<'a> नहीं है करने के लिए एक संदर्भ होना आवश्यक है। इस आवश्यकता को निकाला जा रहा है इस समस्या का हल (यहाँ, नाम alt लगी होती हैं इस तथ्य पर जोर देना इस एक वैकल्पिक इंटरफ़ेस है):

trait AltBorrow<'a, AltBorrowed> { 
    fn alt_borrow(&'a self) -> AltBorrowed; 
} 

trait AltToOwned<'a> { 
    type AltOwned: AltBorrow<'a, Self>; 
    fn alt_to_owned(&'a self) -> Self::AltOwned; 
} 

यह विशेषता तो मानक प्रकार के लिए लागू किया जा सकता है, उदा Vec:

impl<'a, T> AltBorrow<'a, &'a [T]> for Vec<T> { 
    fn alt_borrow(&'a self) -> &'a [T] { 
     self.as_slice() 
    } 
} 

impl<'a, T> AltToOwned<'a> for &'a [T] 
    where T: Clone 
{ 
    type AltOwned = Vec<T>; 

    fn alt_to_owned(&'a self) -> Vec<T> { 
     self.to_vec() 
    } 
} 

साथ ही सवाल में Variant enum के लिए:

impl<'a> AltBorrow<'a, BorrowedVariant<'a>> for OwnedVariant { 
    fn alt_borrow(&'a self) -> BorrowedVariant<'a> { 
     match self { 
      &Variant::Nothing => Variant::Nothing, 
      &Variant::SomeInt(value) => Variant::SomeInt(value), 
      &Variant::SomeBytes(ref value) => Variant::SomeBytes(value.alt_borrow()), 
     } 
    } 
} 

impl<'a> AltToOwned<'a> for BorrowedVariant<'a> { 
    type AltOwned = OwnedVariant; 

    fn alt_to_owned(&'a self) -> OwnedVariant { 
     match self { 
      &Variant::Nothing => Variant::Nothing, 
      &Variant::SomeInt(value) => Variant::SomeInt(value), 
      &Variant::SomeBytes(value) => Variant::SomeBytes(value.alt_to_owned()), 
     } 
    } 
} 

अंत में, सवाल:

  1. मैं मूल Borrow/ToOwned अवधारणा का दुरुपयोग है? क्या मुझे इसे हासिल करने के लिए कुछ और उपयोग करना चाहिए?
  2. यदि नहीं, तो std::borrow से वर्तमान कम-सामान्य इंटरफ़ेस को क्यों पसंद किया जा सकता है?

This example on Rust playpen

उत्तर

3

गॉट some explanation #rust आईआरसी पर।

से aturon:

संक्षिप्त उत्तर है: हम उच्च kinded प्रकार (HKT) आवश्यकता होगी यहां बेहतर करने के लिए; यह, सुचारू रूप से बाद में HKT को "अपग्रेड" करने के लिए संभव हो जाना चाहिए, हालांकि

(विशेषता स्तर तक जीवन उठाने का एक तरीका है (यह एक पैटर्न है कि मानक पुस्तकालय में कुछ स्थानों पर आने रहा है) HKT एन्कोडिंग, लेकिन बनाता है यह काफी अधिक अजीब से bluss विशेषता)

उपयोग करने के लिए:

मैं अपने प्रश्न की तरह। इस तरह के जीवनकाल में पर्याप्त आईएमओ की खोज नहीं की गई है, लेकिन इसमें उधार चेकर में अभी भी ज्ञात बग है

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