Bulan-bulan pertama seorang perusuh pemula biasanya datang ke header tentang konsep seumur hidup dan kepemilikan. Beberapa orang merinci hal ini, tetapi bagi mereka yang mampu bertahan, ini tidak lagi tampak tidak biasa atau salah. Saya akan menjelaskan poin-poin kunci yang, menurut saya, telah membantu untuk beradaptasi lebih cepat dan lebih baik dengan konsep kehidupan dan harta. 
Tentu saja, buletin resmi lebih penuh dan lebih rinci, tetapi juga membutuhkan lebih banyak waktu dan kesabaran untuk sepenuhnya memahami dan menyerap semua informasi. Saya mencoba untuk menghindari sejumlah besar detail dan menyajikan semuanya dalam rangka meningkatkan kompleksitas, dalam upaya untuk membuat artikel ini lebih mudah diakses oleh mereka yang baru mulai menonton pesta, atau tidak benar-benar memahami saat-saat awal dari papan buletin resmi.
Itu juga membuat saya menulis bahwa, misalnya, dari monad, Anda dapat menemukan beberapa materi pelatihan resmi, tetapi mereka tidak selalu dipahami dengan baik, dan pemahaman muncul hanya setelah membaca sesuatu seperti "pengantar lain" pada topik ini.
Seumur hidup
Pertama kita perlu merasa nyaman dengan dua hal - akhir blok dan memindahkan nilainya ke blok lain. Nanti kita akan mulai memperumitnya dengan menambahkan “pinjaman”, “mutabilitas” dan “mutabilitas tersembunyi”.
Pertama-tama, umur suatu nilai ditentukan oleh segmen berikut:
- Awal Kehidupan: Menciptakan Nilai. Ini umum untuk sebagian besar bahasa pemrograman, sehingga tidak membawa muatan yang tidak biasa.
- Akhir hidup. Di sinilah Rust akan secara otomatis memanggil destructor dan melupakan nilainya. Di blok ruang lingkup, ini akan terjadi di akhir blok ini tanpa bergerak. Ini adalah pelacakan mental dari akhir kehidupan yang, menurut pendapat saya, adalah kunci untuk interaksi yang sukses dengan peminjam.
Saya akan menambahkan detail yang mungkin berguna: jika ada beberapa nilai dalam ruang lingkup, maka mereka akan dihancurkan dalam urutan terbalik penciptaan.
Poin lain: Saya akan membuat string, karena tidak memiliki penanda Salin, dan nilai-nilai yang memiliki penanda ini tidak bergerak tetapi disalin, yang dianggap sebagai operasi yang lebih murah, tetapi mengubah perilaku gerakan (dan membuatnya lebih mudah untuk bekerja dengan tipe primitif), tetapi lebih lanjut tentang itu nanti.
Contoh dapat dijalankan di sini: https://play.rust-lang.org/
fn main() { {
Dengan blok sederhana, semuanya relatif sederhana, tahap berikutnya terjadi ketika kita menggunakan hal-hal yang tampaknya sederhana seperti fungsi dan penutupan:
Bergerak
Tambahkan konsep seperti memindahkan nilai. Dengan kata sederhana, "bergerak" berarti bahwa blok saat ini tidak lagi tertarik pada nasib nilai dan melupakannya, dan nasibnya ditransfer ke blok lain, misalnya, ke fungsi lain, atau ke penutupan, atau hanya ke nilai lain.
fn f<T: std::fmt::Display>(x: T) {
Dengan penutupan.
Agar penutupan untuk memindahkan nilai yang ditangkap ke bloknya, gerakan kata kunci digunakan, jika Anda tidak menulis langkah, nilainya dipinjam, yang akan saya tulis segera.
fn main() { let a = "a".to_string();
Anda bisa memindahkan keduanya ke fungsi dan dari fungsi atau ke nilai lain.
Contoh ini menunjukkan bagaimana melacak cara nilai bergerak untuk hidup damai dengan peminjam.
fn f(x: String) -> String { x + " and x"
Pinjaman
Kami memperkenalkan konsep baru ini: tidak seperti bergerak, ini berarti bahwa blok saat ini mengendalikan kontrol nilai, itu hanya memungkinkan blok lain untuk menggunakan nilainya.
Saya perhatikan bahwa pinjaman juga terjadi di mana ia berakhir, yang tidak terlalu penting dalam contoh-contoh ini, tetapi akan muncul di paragraf berikutnya.
Catatan: Saya tidak akan menulis tentang cara menentukan umur langsung di fungsi, karena karat modern melakukan ini secara otomatis lebih baik daripada di masa lalu, dan pengungkapan semua ini adalah beberapa halaman lagi.
fn f(x: &String) {
Dengan penutupan yang sama:
fn main() { let mut a = "a".to_string();
Sebenarnya, di sebagian besar konstruksi sederhana ini, pengguna hanya perlu memutuskan di mana ia ingin mengakhiri umur nilai: di akhir blok saat ini dan meminjamkannya ke beberapa fungsi, atau, jika kita tahu bahwa kita tidak lagi membutuhkan nilai, kemudian pindahkan ke fungsi di akhir dengan mana itu sendiri akan dihancurkan, semakin cepat kita membebaskan memori, tetapi nilainya tidak akan lagi tersedia di blok saat ini.
Mutabilitas
Dalam rasta, seperti, misalnya, di kotlin, ada pembagian ke dalam nilai yang bisa berubah dan tidak stabil. Tetapi timbul masalah bahwa ketidakstabilan berdampak pada peminjaman:
Anda dapat meminjam nilai yang tidak stabil berkali-kali, dan nilai yang dapat berubah dapat dipinjam satu kali saja. Anda tidak dapat mengubah nilai yang sudah dipinjam sebelumnya.
Contoh yang tidak terkait dengan yang sebelumnya, ketika konsep ini menyelamatkan kita dari masalah dengan melarang peminjaman yang simultan dan tidak stabil:
fn main() { let mut a = "abc".to_string(); for x in a.chars() {
Di sini sudah perlu untuk menyimpan berbagai trik untuk memuaskan, sebagian besar, klaim rasta yang adil. Pada contoh di atas, yang paling mudah adalah mengkloning "a" -> klon akan memiliki pinjaman yang tidak stabil, dan tidak berhubungan dengan "a" yang asli.
for x in a.clone().chars() {
Tapi saya lebih baik kembali ke contoh kita untuk menjaga konsistensi. Kita perlu mengubah "a" dan kita tidak bisa melakukannya.
fn main() { let mut a = "a".to_string();
Mutasi tersembunyi
Secara teoritis, penutupan dapat diteruskan ke beberapa fungsi yang memproses, misalnya, secara asinkron di utas lainnya, dan kemudian kita benar-benar akan mengalami masalah, tetapi dalam kasus ini, peminjam cek direasuransikan, meskipun ini tidak membatalkan fakta bahwa kita perlu menyetujui dengan suatu cara .
Intinya: kita membutuhkan dua pinjaman bermutasi, tetapi yang terakhir hanya memungkinkan satu hal, tetapi penemu licik dari rasta datang dengan "mutasi tersembunyi": RefCell.
RefCell - apa yang kita bungkus dalam RefCell - raster menganggapnya nemable, namun, menggunakan fungsi meminjam_mut () kita dapat mengekstraksi sementara tautan yang dapat diubah untuk sementara waktu yang dapat mengubah nilai, tetapi ada nuansa penting : tautan hanya dapat diperoleh ketika RefCell saat runtime memastikan bahwa tidak ada yang lain pinjaman aktif, jika tidak, dia akan panik, atau mengembalikan kesalahan jika try_borrow_mut () digunakan. Yaitu di sini pertumbuhan memberikan semua kekhawatiran tentang pemberian pinjaman kepada pengguna, dan dia sendiri harus memastikan bahwa dia tidak meminjam nilai dari beberapa tempat sekaligus.
use std::cell::RefCell; fn main() { let a = RefCell::new("a".to_string());
Penghitung Tautan Rc
Konstruksi ini dikenal dalam banyak bahasa, dan digunakan dalam rast, ketika, misalnya, kami tidak dapat meminjam nilai karena suatu alasan, dan ada kebutuhan untuk memiliki beberapa nilai referensi untuk satu nilai tunggal. Rc, seperti namanya, hanyalah penghitung referensi yang memiliki nilai, Rc dapat meminjam tautan yang tidak dapat diandalkan, menghitung jumlah mereka, dan segera setelah nomornya diatur ulang, Rc akan menghancurkan nilai itu sendiri. Ternyata Rc memungkinkan, seolah-olah, untuk secara diam-diam memperluas umur dari nilai yang terkandung di dalamnya.
Saya akan menambahkan bahwa rast dapat secara otomatis melakukan deref untuk struktur yang didefinisikan, yang berarti bahwa untuk bekerja dengan Rc, sebagai aturan, Anda tidak memerlukan ekstraksi tambahan dari nilai internal dan kami hanya bekerja dengan Rc seperti halnya dengan nilai di dalamnya.
Di sini contoh sederhana dianggap agak sulit, mari kita coba meniru bahwa penutupan dari contoh di atas tidak ingin menerima & T atau & String, tetapi hanya ingin String:
fn f(x: String) {
Masalah ini akan mudah dipecahkan jika kita dapat mengubah fungsi menjadi fn f(x: &String)
(atau & str), tetapi mari kita bayangkan bahwa karena alasan tertentu kita tidak dapat menggunakan &
Kami menggunakan Rc
use std::rc::Rc; fn f(x: Rc<String>) {
Saya akan menambahkan contoh terakhir, karena salah satu pasangan wadah yang paling sering ditemukan adalah Rc <RefCell>
use std::rc::Rc; use std::cell::RefCell; fn f(x: Rc<RefCell<String>>) { x.borrow_mut().push_str(" and x");
Lebih lanjut, akan logis untuk memindahkan tutorial ini ke analog thread-safe Rc-Arc dan kemudian melanjutkan tentang Mutex, tetapi Anda tidak akan berbicara tentang keamanan thread dan peminjam pinjaman dalam satu paragraf, dan tidak jelas apakah jenis artikel ini diperlukan sama sekali, karena ada utas resmi. Jadi saya menyimpulkan.