2015-05-06 24 views
5

Hãy tưởng tượng một số nguồn sự kiện, tạo ra các sự kiện được biểu diễn dưới dạng enum. Tất nhiên, cho hiệu quả tốt nhất, nhà sản xuất này là zero-sao chép, tức là nó sẽ trả về tham chiếu đến bộ đệm nội bộ của mình:Tại sao đặc điểm Mượn yêu cầu loại vay phải là tham chiếu?

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

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

Đây là hoàn toàn tốt đẹp cho người tiêu dùng mà không cần lookahead hay dấu vết quay, nhưng đôi khi có một cần lưu một số chuỗi sự kiện. Vì vậy, loại Variant của chúng tôi sẽ trở thành một generic:

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

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

Ở đây, chúng tôi kết thúc với hai loại với "chủ sở hữu tài liệu tham khảo" mối quan hệ, mà là tương tự như cặp Vec<T> - &[T], String-&str. Documents đề nghị đặc điểm BUILTIN BorrowToOwned cung cấp chỉ là những gì được yêu cầu ngoại trừ một sắc thái tinh tế:

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

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

Kết quả borrow là cần thiết để trở thành một tài liệu tham khảo một cái gì đó, mà BorrowedVariant<'a> rõ ràng là không. Loại bỏ yêu cầu này giải quyết vấn đề này (ở đây, tên được bắt đầu với alt để nhấn mạnh một thực tế đây là một giao diện thay thế):

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; 
} 

đặc điểm này sau đó có thể được thực hiện với nhiều loại tiêu chuẩn, ví dụ 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() 
    } 
} 

Cũng như cho Variant enum trong câu hỏi:

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()), 
     } 
    } 
} 

Cuối cùng, câu hỏi:

  1. Tôi lợi dụng bản gốc Borrow/ToOwned khái niệm? Tôi có nên sử dụng cái gì khác để đạt được điều này?
  2. Nếu không, thì lý do tại sao giao diện ít chung chung hiện tại từ std::borrow có thể đã được ưu tiên hơn?

This example on Rust playpen

Trả lời

3

Got some explanation trên #rust IRC.

Từ aturon:

câu trả lời ngắn gọn là: chúng tôi cần loại cao kinded (HKT) để thực hiện tốt hơn ở đây; chúng ta có thể để trơn tru "nâng cấp" để HKT sau này, mặc dù

(đây là một mô hình đó là đưa ra một vài nơi trong thư viện chuẩn)

(nâng tuổi thọ đến mức đặc điểm là một cách của mã hóa HKT, nhưng làm cho nó đáng kể vụng về hơn để sử dụng các đặc điểm)

Từ bluss:

tôi thích câu hỏi của bạn. Đó là loại cuộc đời trong một đặc điểm chưa được khám phá đủ IMO nhưng nó cũng có một lỗi đã biết trong người kiểm tra vay ngay bây giờ

Các vấn đề liên quan