Buku Pemrograman Rust

gambarHalo para Penduduk! Panduan Bahasa Pemrograman Rust Resmi akan membantu Anda membuat perangkat lunak yang lebih cepat dan lebih andal. Ergonomi tingkat tinggi dan kontrol tingkat rendah sering bertentangan satu sama lain, tetapi Rust menantang konflik ini.



Penulis buku ini adalah bagian dari tim pengembangan bahasa, yang berarti Anda akan menerima semua informasi secara langsung - mulai dari menginstal bahasa hingga membuat program yang andal dan dapat diskalakan. Dari membuat fungsi, memilih tipe data, dan mengikat variabel, Anda akan beralih ke konsep yang lebih kompleks:



  • Kepemilikan dan peminjaman, siklus hidup dan jenis.
  • Keamanan perangkat lunak terjamin.
  • Pengujian, penanganan kesalahan, dan pemfaktoran ulang yang efektif.
  • Generik, smart pointer, multithreading, objek ciri, dan pemetaan.
  • Bekerja dengan pengelola paket bawaan Cargo untuk membangun, menguji, mendokumentasikan kode, dan mengelola dependensi.
  • Alat canggih untuk bekerja dengan Unsafe Rust.


Anda akan menemukan banyak contoh kode, serta tiga bab tentang membangun proyek lengkap untuk memperkuat pengetahuan Anda: menebak game, membangun alat baris perintah, dan server multi-utas.



Untuk siapa buku ini



Kami berasumsi bahwa Anda menulis kode Anda dalam bahasa pemrograman yang berbeda, tetapi kami tidak berasumsi tentang yang mana. Kami telah mencoba membuat materi ini dapat diakses oleh mereka yang memiliki berbagai keterampilan pemrograman. Kami tidak akan membuang waktu untuk membicarakan tentang apa itu pemrograman. Jika Anda benar-benar pemula dalam pemrograman, maka pertama-tama baca pengantar pemrograman.



Bagaimana menggunakan buku ini
-, , , . , ; .



: . . , , . 2, 12 20 , β€” .



1 , Rust, Β«Hello, World!Β» Cargo. 2 Rust. , . , . 3, Rust, , 4 Rust. , , 2, 3, 2, . , .



5 , 6 , match if let. Rust .



7 (API). 8 , , , -. 9 .



10 , , , . 11 , Rust . 12 grep, . , .



13 β€” , . 14 Cargo . 15 , , , .



16 , Rust . 17 Rust - , , , .



18 , Rust. 19 , , Rust, , , .

20 , !



, . Rust, Rust, , , , Rust.



: -, ! - , , , . , , .



Rust β€” , : . , , . , , ! , , , , . , .



Dimana pola bisa digunakan



Di Rust, pola muncul di banyak tempat, dan Anda sering menggunakannya tanpa menyadarinya! Bagian ini membahas situasi di mana polanya valid.



Cabang ekspresi pertandingan



Seperti yang dibahas di Bab 6, kami menggunakan pola di cabang ekspresi kecocokan. Secara formal, ekspresi pencocokan didefinisikan sebagai kata kunci pencocokan, lalu nilai yang akan dicocokkan, dan satu atau beberapa cabang pencocokan yang terdiri dari pola dan ekspresi yang akan dieksekusi jika nilai cocok dengan pola dari cabang tersebut, misalnya:



   match  {
           => ,
           => ,
           => ,
   }


Salah satu syarat ekspresi match adalah harus komprehensif, dalam artian semua kemungkinan nilai harus diperhatikan dalam match. Agar Anda dapat mempertimbangkan semua opsi yang memungkinkan, Anda perlu memiliki pola yang mencakup semua di cabang terakhir: misalnya, nama variabel yang cocok dengan nilai apa pun akan selalu berfungsi dan dengan demikian mencakup semua kasus yang tersisa.



Pola khusus _ akan cocok dengan apa pun, tetapi tidak terikat ke variabel dan oleh karena itu sering digunakan di lengan pencocokan terakhir. Pola _ berguna, misalnya, jika Anda ingin mengabaikan nilai yang tidak ditentukan. Kami akan mempertimbangkan pola lebih detail di bagian "Mengabaikan nilai dalam pola".



Jika biarkan kondisional



Dalam Bab 6, kita membahas pernyataan if let terutama sebagai cara yang lebih singkat untuk menulis padanan ekspresi pencocokan, yang hanya cocok dengan satu kasus. Alternatifnya, if let dapat memiliki pencocokan lain yang berisi kode untuk dieksekusi jika pola dalam if let tidak cocok.



Kode 18.1 menunjukkan bahwa dimungkinkan juga untuk mencampur dan mencocokkan pernyataan if let, else if, dan else if let. Ini memberi kami lebih banyak fleksibilitas daripada menggunakan ekspresi pencocokan, yang hanya dapat mengekspresikan satu nilai untuk dibandingkan dengan pola. Selain itu, kondisi dalam rangkaian pernyataan if let, else if, dan else if let tidak perlu merujuk satu sama lain.



Kode pada Listing 18.1 menunjukkan serangkaian tes untuk beberapa kondisi yang menentukan seperti apa warna latar belakang. Dalam contoh ini, kami membuat variabel dengan nilai hard-code yang dapat diambil oleh program nyata dari input pengguna.



Daftar 18.1. Mencampur if let, else if, else if let dan else statement



src/main.rs
      fn main() {
             let favorite_color: Option<&str> = None;
             let is_tuesday = false;
             let age: Result<u8, _> = "34".parse();

      (1) if let Some(color) = favorite_color {
          (2) println!("   , {},   ", color);
      (3) } else if is_tuesday {
          (4) println!(" -  !");
      (5) } else if let Ok(age) = age {
          (6) if age > 30 {
               (7) println!("     ");
              } else {
               (8) println!("     ");
              }
      (9) } else {
          (10) println!("     ");
           }
     }


Jika pengguna menentukan warna favorit (1), maka ini adalah warna latar belakang (2). Jika hari ini adalah Selasa (3), maka warna latarnya hijau (4). Jika pengguna menentukan usianya sebagai string dan kami berhasil menguraikannya sebagai angka (5), maka warnanya akan menjadi ungu (7) atau oranye (8) tergantung pada nilai angka (6). Jika tidak satu pun dari ketentuan ini berlaku (9), maka warna latar belakangnya adalah biru (10).



Struktur bersyarat ini memungkinkan adanya persyaratan yang kompleks. Dengan nilai hardcode yang ada di sini, contoh ini akan keluar



     .


Anda dapat melihat bahwa ekspresi if let juga dapat memperkenalkan variabel berbayang dengan cara yang sama seperti lengan ekspresi pencocokan: baris kode if let Ok (age) = age (5) memperkenalkan variabel berarsir baru yang berisi nilai di dalam varian Ok. Artinya kita perlu menempatkan kondisi jika usia> 30 dalam blok ini (6): kita tidak dapat menggabungkan kedua kondisi ini dalam pernyataan jika Ok (usia) = usia && usia> 30. Variabel usia yang diarsir ingin kita bandingkan dengan 30 , tidak valid hingga cakupan baru dimulai dengan tanda kurung kurawal.



Kerugian dari menggunakan pernyataan if let adalah bahwa kompilator tidak memeriksa ketelitiannya, sementara ia memeriksa pernyataan kecocokan. Jika kita melewatkan blok else (9) terakhir dan, oleh karena itu, menangani beberapa kasus, kompilator tidak akan memperingatkan kita tentang kemungkinan kesalahan logika.



Sementara biarkan loop bersyarat



Mirip dalam konstruksi dengan pernyataan if let, while let conditional loop memungkinkan perulangan while untuk berjalan selama polanya cocok. Contoh pada Listing 18.2 menunjukkan while let loop yang menggunakan vektor sebagai tumpukan dan mengeluarkan nilai-nilai dalam vektor dalam urutan terbalik dari urutan penambahannya.



Daftar 18.2. Menggunakan while let loop untuk mencetak nilai sementara stack.pop () mengembalikan Some



    let mut stack = Vec::new();

    stack.push(1);
    stack.push(2);
    stack.push(3);

    while let Some(top) = stack.pop() {
          println!("{}", top);
    }


Contoh ini mencetak 3, 2, dan kemudian 1. Metode pop mengambil elemen terakhir dari vektor dan mengembalikan Some (nilai). Jika vektor kosong, maka pop mengembalikan None. Perulangan while terus mengeksekusi kode di bloknya sampai pop mengembalikan Some. Saat pop mengembalikan None, loop berhenti. Kita bisa menggunakan while let conditional loop untuk menghapus setiap item dari stack.



Untuk loop



Dalam Bab 3 kami menyebutkan bahwa perulangan for adalah konstruksi perulangan yang paling umum dalam kode Rust, tetapi kami belum membahas pola yang untuk take. Dalam loop for, polanya adalah nilai yang segera mengikuti kata kunci for, jadi untuk x di y, polanya adalah x.



Kode 18.3 menunjukkan penggunaan pola dalam loop for untuk merusak, atau mendekomposisi, tupel di dalam for.



Daftar 18.3. Menggunakan pola dalam perulangan for untuk menghancurkan tupel



   let v = vec!['a', 'b', 'c'];

   for (index, value) in v.iter().enumerate() {
        println!("{}    {}", value, index);
   }


Kode dalam Listing 18.3 menampilkan berikut ini:



       0
   b    1
       2


Kami menggunakan metode enumerate untuk menulis ulang iterator untuk menghasilkan nilai dan indeks dari nilai tersebut di iterator, ditempatkan di tupel. Panggilan pertama ke metode enumerate menghasilkan tupel (0, 'a'). Jika nilai ini digabungkan dengan pola (indeks, nilai), maka indeks adalah 0 dan nilai adalah 'a', baris pertama data adalah keluaran.



Biarkan pernyataan



Sebelum bab ini, kita secara langsung membahas penggunaan pola hanya dengan pernyataan match dan if let, tetapi sebenarnya kita telah menggunakan pola di tempat lain, termasuk dalam pernyataan let. Pertimbangkan cara sederhana untuk meneruskan nilai variabel menggunakan let:



let x = 5;


Kami telah menggunakan pernyataan biarkan ratusan kali di sepanjang buku ini, dan meskipun Anda mungkin tidak menyadarinya, Anda telah menggunakan pola! Secara lebih formal, pernyataan let terlihat seperti ini:



let  = ;


Dalam pernyataan seperti misalkan x = 5; dengan nama variabel di slot POLA, nama variabel hanyalah bentuk sederhana dari pola. Rust membandingkan ekspresi dengan pola dan memberikan nama yang ditemukannya. Oleh karena itu, dalam contoh misalkan x = 5; polanya adalah x, yang berarti "mengasosiasikan apa yang cocok di sini dengan variabel x". Karena nama x mewakili keseluruhan pola, pola ini secara efektif berarti "ikat semuanya ke variabel x, berapa pun nilainya".



Untuk melihat pemetaan ke pola pernyataan let lebih jelas, pertimbangkan Listing 18.4, yang menggunakan pola let untuk merusak tupel.



Daftar 18.4. Menggunakan pola untuk merusak tupel dan membuat tiga variabel sekaligus



let (x, y, z) = (1, 2, 3);


Di sini kami memetakan tupel ke pola. Rust membandingkan (1, 2, 3) dengan (x, y, z) dan melihat bahwa nilai ini cocok dengan pola, jadi Rust menghubungkan 1 dengan x, 2 dengan y, dan 3 dengan z. Anda dapat menganggap pola tupel ini sebagai tiga pola variabel terpisah di dalamnya.

Jika jumlah elemen dalam pola tidak sesuai dengan jumlah elemen di tupel, maka jenis agregat tidak akan cocok dan kita akan mendapatkan kesalahan kompiler. Sebagai contoh, Listing 18.5 menunjukkan upaya untuk menghancurkan tiga tupel menjadi dua variabel, yang tidak akan bekerja.



Daftar 18.5. Konstruksi pola yang salah, variabel yang tidak sesuai dengan jumlah elemen dalam tupel



let (x, y) = (1, 2, 3);


Mencoba mengompilasi kode ini menghasilkan kesalahan seperti:



error[E0308]: mismatched types
  --> src/main.rs:2:9
   |
2 |        let (x, y) = (1, 2, 3);
   |           ^^^^^^ expected a tuple with 3 elements, found one with 2 elements
   |
   = note: expected type `({integer}, {integer}, {integer})`
                    found type `(_, _)`


Jika kita ingin mengabaikan satu atau lebih nilai dalam tupel, kita bisa menggunakan _ atau .., seperti yang akan Anda lihat di bagian "Mengabaikan nilai dalam pola". Jika masalahnya adalah terlalu banyak variabel dalam pola, maka Anda perlu membuat jenis yang cocok dengan menghapus variabel sehingga jumlah variabel sama dengan jumlah elemen dalam tupel.



Parameter fungsi



Parameter fungsi juga bisa berupa pola. Kode pada Listing 18.6 yang mendeklarasikan sebuah fungsi foo yang mengambil satu parameter x tipe i32 sekarang sudah tidak asing lagi bagi Anda.



Daftar 18.6. Tanda tangan fungsi menggunakan pola dalam parameter



fn foo(x: i32) {
     //   
}


Bagian x adalah pola! Seperti let, kita bisa mencocokkan tupel dalam argumen fungsi dengan pola. Kode 18.7 memecah nilai-nilai dalam tupel ketika kita meneruskannya ke dalam fungsi.



Daftar 18.7. Fungsi dengan parameter yang merusak tupel



src/main.rs
      fn print_coordinates(&(x, y): &(i32, i32)) {
            println!(" : ({}, {})", x, y);
      }

      fn main() {
            let point = (3, 5);
            print_coordinates(&point);
      }


Kode ini menghasilkan



 : (3, 5)


Nilai & (3, 5) cocok dengan pola & (x, y), jadi x adalah 3 dan y adalah 5.

Sebagai tambahan, kita dapat menggunakan pola dalam daftar parameter closure dengan cara yang sama seperti dalam daftar parameter fungsi, karena closure mirip dengan fungsi, seperti dijelaskan pada Bab 13.



Anda telah melihat beberapa cara untuk menggunakan pola, tapi cara kerjanya tidak sama di mana pun Anda menggunakannya. Dalam beberapa situasi, pola ini harus tak terbantahkan; dalam situasi lain, bisa disangkal. Kami akan membahas kedua konsep tersebut di bawah ini.



Dapat disanggah: kemungkinan ketidakcocokan pola



Ada dua jenis pola: dapat disangkal dan tidak dapat disangkal. Pola yang akan cocok dengan nilai yang mungkin dilalui tidak dapat disangkal. Contohnya adalah x dalam pernyataan let x = 5; karena x benar-benar cocok dengan semuanya dan oleh karena itu tidak bisa tidak cocok. Pola-pola yang tidak cocok dengan beberapa kemungkinan arti dapat dibantah. Contohnya adalah Some (x) dalam pernyataan if let Some (x) = a_value, karena jika nilai dalam a_value adalah None dan bukan Some, maka Some (x) tidak akan cocok.



Parameter fungsi, pernyataan let, dan untuk perulangan hanya dapat menerima pola yang tidak dapat disangkal karena program tidak dapat melakukan sesuatu yang berarti jika nilainya tidak cocok. Ekspresi if let dan while let hanya menerima pola sanggahan, karena menurut definisi mereka dirancang untuk menangani kemungkinan kesalahan: fungsionalitas ekspresi kondisional adalah kemampuannya untuk melakukan tindakan yang berbeda tergantung pada keberhasilan atau kegagalan.



Secara umum, Anda tidak perlu khawatir tentang perbedaan antara pola yang dapat disangkal dan yang tidak dapat disangkal. Namun, Anda masih perlu mengetahui konsep sanggahan untuk bereaksi ketika Anda melihatnya dalam pesan kesalahan. Dalam kasus ini, Anda perlu mengubah pola atau konstruksi yang Anda gunakan untuk menggunakan pola tersebut, bergantung pada perilaku kode yang diinginkan.



Mari kita lihat apa yang terjadi ketika kita mencoba menggunakan pola tak terbantahkan di tempat di mana Rust membutuhkan pola tak terbantahkan, dan sebaliknya. Kode 18.8 menunjukkan pernyataan let, tetapi untuk pola yang kami tentukan Beberapa (x), pola sanggahan. Seperti yang Anda duga, kode ini tidak dapat dikompilasi.



Daftar 18.8. Mencoba menggunakan pola sanggahan dengan membiarkan



let Some(x) = some_option_value;


Jika some_option_value sama dengan None, maka itu tidak akan sesuai dengan pola Some (x), yaitu polanya dapat disangkal. Namun, pernyataan let hanya dapat menerima pola yang tidak dapat disangkal, karena kode tidak dapat melakukan apa pun yang valid dengan nilai None. Pada waktu kompilasi, Rust akan mengeluh bahwa kami mencoba menggunakan pola rebuttable di mana diperlukan pola yang tak terbantahkan:



error[E0005]: refutable pattern in local binding: `None` not covered
  -->
   |
3 | let Some(x) = some_option_value;
   |     ^^^^^^^ pattern `None` not covered


Karena kita belum membahas (dan tidak bisa menutupi!) Setiap nilai yang valid dengan pola Some (x), Rust berhak membuat kesalahan kompilator.



Untuk memperbaiki masalah ketika kita memiliki pola yang dapat disangkal dan bukan pola yang tidak dapat disangkal, kita dapat mengubah kode yang menggunakan pola tersebut: daripada membiarkan, kita dapat menggunakan jika membiarkan. Kemudian, jika polanya tidak cocok, maka kode dalam tanda kurung kurawal akan dilewati dan pekerjaan akan dilanjutkan dengan benar. Listing 18.9 menunjukkan bagaimana memperbaiki kode pada Listing 18.8.



Daftar 18.9. Menggunakan pernyataan if let dan blok pola sanggahan alih-alih membiarkan



if let Some(x) = some_option_value {
    println!("{}", x);
}


Kode sudah siap! Ini adalah kode yang benar-benar benar, meskipun itu berarti kita tidak dapat menggunakan pola yang tidak terbantahkan tanpa kesalahan. Jika kita memberikan ekspresi if let pola yang akan selalu cocok, seperti x, seperti yang ditunjukkan pada Listing 18-10, maka itu tidak akan dikompilasi.



Daftar 18.10. Mencoba menggunakan pola yang tak terbantahkan dengan pernyataan if let



if let x = 5 {
    println!("{}", x);
};


Kompilator mengeluh bahwa tidak masuk akal menggunakan ekspresi if let dengan pola yang tak terbantahkan:



error[E0162]: irrefutable if-let pattern
  --> <anon>:2:8
   |
2 | if let x = 5 {
   |        ^ irrefutable pattern


Untuk alasan ini, lengan ekspresi pencocokan harus menggunakan pola yang dapat disangkal, dengan pengecualian lengan terakhir, yang harus mencocokkan nilai yang tersisa dengan pola yang tidak dapat disangkal. Rust memungkinkan pola yang tak terbantahkan untuk digunakan dalam ekspresi kecocokan dengan hanya satu lengan, tetapi sintaksis ini tidak terlalu berguna dan dapat diganti dengan pernyataan let yang lebih sederhana.



Sekarang setelah Anda tahu di mana pola digunakan, dan bagaimana pola yang dapat disangkal dan tidak dapat disangkal berbeda, mari kita mengenal sintaks yang dapat kita gunakan untuk membuat pola.



Tentang Penulis



Steve Klabnik memimpin tim dokumentasi Rust dan merupakan salah satu pengembang utama bahasa tersebut. Dia adalah dosen yang sering dan menulis banyak kode sumber terbuka. Sebelumnya mengerjakan proyek seperti Ruby dan Ruby on Rails.



Carol Nichols adalah anggota tim pengembangan Rust Core dan salah satu pendiri Integer 32, LLC, perusahaan konsultan pengembangan perangkat lunak pertama yang berfokus pada Rust di dunia. Nichols adalah penyelenggara konferensi Rust Belt tentang bahasa Rust.



Β»Rincian lebih lanjut tentang buku dapat ditemukan di situs web penerbit

Β» Daftar Isi

Β» Kutipan



Untuk Habitans diskon 25% untuk kupon - Rust



Setelah pembayaran untuk versi kertas dari buku tersebut, sebuah e-book dikirim ke email.



All Articles