Berikut adalah struct mainan yang berisi vektor

struct SizedVec {
    items: Vec<u32>,
    cap: usize,
}

Saya ingin memiliki fungsi iterasi pada SizedVec sehingga mereka akan berfungsi seolah-olah saya mengulangi item secara langsung.

Namun, saya tidak yakin sifat mana yang harus saya terapkan: apakah Iterator dan IntoIterator cukup? Ada banyak ciri di dokumen dan mereka tampak agak rumit dan membosankan.

Kemudian saya melihat bahwa saya dapat mengimplementasikan Deref dan DerefMut dan mendapatkan semua fungsi tersebut secara gratis menggunakan deref coercion:

Benar saja, setelah melakukan ini:

impl Deref for SizedVec {
    type Target = Vec<u32>;

    fn deref(&self) -> &Self::Target {
        &self.items
    }
}

impl DerefMut for SizedVec {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.items
    }
}

Saya dapat menggunakan semua iterator yang saya inginkan. Tapi saya ingin menerapkan logika khusus untuk Push, tetapi DeRef sudah memberi saya Push. Tetapi menurut dokumen saya seharusnya baik-baik saja karena tampaknya pencarian dilakukan untuk setiap jenis secara berurutan

impl SizedVec {
    fn from_size(size: usize) -> Self {
        Self {
            items: vec![],
            cap: size,
        }
    }

    fn push(&mut self, item: u32) {
        if self.items.len() < self.cap {
            self.items.push(item);
        }else {
            self.items.pop();
            self.items.push(item);
        }
    }
}

Dan ini tampaknya berhasil,

fn main () {
    let mut svec = SizedVec::from_size(2); // Custom function I implemented
    svec.push(2);
    svec.push(3);
    svec.push(4);
    svec.iter_mut().for_each(|item| {*item = *item + 2});
    println!("{}", svec); // Items: [4, 6], Cap: 2 (Implemented Display so this works)
}

Ini semua tampaknya bekerja dengan sangat baik, tetapi pertanyaan saya adalah: apakah ini ide yang bagus? Apakah saya akan mengalami masalah jika saya mengonversi SizedVec saya ke tipe generik?

Jika ini adalah ide yang buruk, apakah ada cara sederhana saya bisa mendapatkan semua iterasi/fungsi peta dari item vektor dalam ke struct terlampir?

Juga, apakah ada pertimbangan kinerja untuk ini?

0
Vikash B 12 Mei 2021, 04:50

1 menjawab

Jawaban Terbaik

Deref baik-baik saja karena struktur Anda secara khusus adalah vec dengan invarian tambahan (jadi membuatnya dapat digunakan sebagai sebuah vec tampaknya masuk akal) tetapi DerefMut sepertinya ide yang agak buruk karena akan biarkan penelepon membocorkan Vec internal (sebagai referensi yang bisa berubah) dan merusak invarian Anda.

Salah satu opsi mungkin adalah Deref ke irisan (bukan vec), dalam hal ini DerefMut juga akan memberi Anda irisan, yang memiliki batasan yang cukup parah dan dengan demikian tidak akan dapat merusak invarian. Itu berarti Anda mungkin perlu mengimplementasikan kembali metode Vec yang melekat, dan tidak akan dapat dianggap sebagai Vec.

Opsi lain adalah tidak mengimplementasikan DerefMut sama sekali, dan memiliki metode yang lebih eksplisit untuk ini. Juga WRT iterables, perhatikan bahwa Anda hanya perlu mengimplementasikan IntoIterator dan metode penghasil iterator lainnya (.iter(), .iter_mut()): hasilnya bisa berupa iterator apa pun yang dikembalikan oleh koleksi yang mendasarinya.

Sekarang saya tidak tahu apa yang Anda maksud dengan

Namun, saya tidak yakin sifat mana yang harus saya terapkan: apakah Iterator [...] cukup?

Anda tidak boleh, dalam keadaan apa pun, menerapkan Iterator langsung di SizedVec Anda. Itu adalah ide yang mengerikan, mengerikan.

Sub-sifat iterator pada dasarnya adalah penanda, mereka menyediakan fitur tambahan di atas Iterator (tetapi tidak selalu dapat diimplementasikan oleh setiap jenis Iterator). Jika Anda mendelegasikan iterasi Anda dengan benar, tipe iterator yang mendasarinya kemungkinan akan mengimplementasikan yang mungkin.

5
Masklinn 12 Mei 2021, 05:39