Cow
Cow adalah enum yang cukup membantu. Ia singkatan dari "clone on write" dan memungkinkan Anda mengembalikan &str
jika Anda tidak membutuhkan String
, dan mengembalikan String
jika Anda memerlukannya. (Ia juga bisa melakukan hal yang sama pada array vs. Vecs, dan lainnya.)
Untuk memahami ini, mari kita lihat signaturenya. Seperti ini:
pub enum Cow<'a, B> where B: 'a + ToOwned + ?Sized, { Borrowed(&'a B), Owned(<B as ToOwned>::Owned), } fn main() {}
Anda langsung mengetahui bahwa 'a
artinya ia bekerja dengan reference. Trait ToOwned
artinya bahwa ia adalah type yang bisa diubah menjadi sebuah owned type. Contohnya, str
biasanya adalah reference (&str
) dan Anda bisa mengubahnya menjadi owned type seperti String
.
Selanjutnya adalah ?Sized
. Ini berari "mungkin Sized, mungkin juga bukan". Hampis semua type di dalam Rust adalah Sized, namun type seperti str
adalah bukan. Itulah mengapa kita memerlukan &
untuk str
, karen compiler tidak mengetahui sizenya. Sehingga, jika Anda menginginkan sebuah trait yang bisa menggunakan sesuatu seperti str
, Anda tambahkan ?Sized.
Selanjutnya adalah variant enum
nya. Yaitu Borrowed
dan Owned
.
Bayangkan, Anda memiliki function yang mengembalikan Cow<'static, str>
. Jika Anda memberitahu function untuk mengembalikan "My message".into()
, ia akan memeriksa pada typenya: "My message" adalah str
. Ini merupakan type Borrowed
, jadi ia memilih Borrowed(&'a B)
. Sehingga ia menjadi Cow::Borrowed(&'static str)
.
Dan jika Anda memberikan format!("{}", "My message").into()
, ia pun akan memeriksa typenya. Dan ini merupakan String
, karena format!
membuat sebuah String
. Sehingga untuk kali ini ia akan memilih "Owned".
Ini adalah contoh untuk melakukan test pada Cow
. Kita akan meletakkan sebuah angka ke dalam function yang mengembalikan Cow<'static, str>
. Kita akan membuat sebuah &str
atau String
, tergantung dari angkanya. Kemudian ia menggunakan .into()
untuk mengubahnya menjadi Cow
. Di saat Anda melakukan hal tersebut, ia akan memilih antara Cow::Borrowed
atau Cow::Owned
. Kemudian kita gunakan match untuk melihat yang mana yang akan dipilih oleh Cow
.
use std::borrow::Cow; fn modulo_3(input: u8) -> Cow<'static, str> { match input % 3 { 0 => "Remainder is 0".into(), 1 => "Remainder is 1".into(), remainder => format!("Remainder is {}", remainder).into(), } } fn main() { for number in 1..=6 { match modulo_3(number) { Cow::Borrowed(message) => println!("{} went in. The Cow is borrowed with this message: {}", number, message), Cow::Owned(message) => println!("{} went in. The Cow is owned with this message: {}", number, message), } } }
Hasilnya adalah:
1 went in. The Cow is borrowed with this message: Remainder is 1
2 went in. The Cow is owned with this message: Remainder is 2
3 went in. The Cow is borrowed with this message: Remainder is 0
4 went in. The Cow is borrowed with this message: Remainder is 1
5 went in. The Cow is owned with this message: Remainder is 2
6 went in. The Cow is borrowed with this message: Remainder is 0
Cow
memiliki method yang lain seperti into_owned
atau into_borrowed
sehingga Anda bisa menggantinya jika Anda merasa perlu melakukannya.