Variabel dan Mutability

let, immutability sebagai bawaan, dan shadowing.

Daftar isi

Topik ini membahas cara menyimpan nilai di dalam variabel Rust dengan let, alasan variabel Rust bersifat tidak dapat diubah secara bawaan, cara mengizinkan perubahan dengan mut, serta mekanisme shadowing yang membuat variabel baru bernama sama. Setelah membacanya, pembaca dapat memilih secara sadar antara variabel yang dapat diubah dan yang tidak, serta membedakan keduanya dari konstanta.

Variabel dengan let#

Variabel dibuat dengan pernyataan let yang diikuti nama variabel, tanda sama dengan, dan nilai awalnya. Nilai tersebut tersimpan untuk dipakai pada baris-baris berikutnya, seperti pada program berikut.

rust dasar.rs
fn main() {
    let x = 5;
    println!("nilai x: {x}");
}
text Keluaran
nilai x: 5

Tipe variabel tidak perlu dituliskan karena Rust menyimpulkannya dari nilai yang diberikan. Nilai 5 pada konteks ini menghasilkan tipe i32, yaitu tipe bilangan bulat bertanda yang menjadi pilihan bawaan compiler ketika tidak ada petunjuk lain. Penyimpulan tipe (type inference) ini tidak mengubah sifat Rust sebagai bahasa bertipe statis, sebab tipe setiap variabel tetap ditetapkan sepenuhnya saat kompilasi dan tidak berubah lagi selama variabel hidup. Nama variabel ditulis dengan huruf kecil dan kata dipisah garis bawah, misalnya nilai_maks atau sisa_kursi, dan konvensi ini dijaga compiler lewat peringatan non_snake_case apabila nama seperti NilaiMaks dipakai.

Variabel tidak dapat diubah secara bawaan#

Satu keputusan desain Rust yang membedakannya dari banyak bahasa lain adalah variabel yang dibuat dengan let bersifat tidak dapat diubah (immutable) sejak awal. Penugasan nilai baru ke variabel semacam itu ditolak compiler. Program berikut sengaja berisi kesalahan tersebut.

bash
printf 'fn main() {\n    let x = 5;\n    println!("nilai x: {x}");\n    x = 6;\n}\n' > salah.rs
rustc --edition=2021 salah.rs 2>&1 | sed -n '1,14p'
text Keluaran
error[E0384]: cannot assign twice to immutable variable `x`
 --> salah.rs:4:5
  |
2 |     let x = 5;
  |         - first assignment to `x`
3 |     println!("nilai x: {x}");
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable
  |
help: consider making this binding mutable
  |
2 |     let mut x = 5;
  |         +++

Error E0384 menunjuk baris penugasan ulang dan menawarkan perbaikan berupa penambahan mut pada deklarasi. Baris penugasan pertama ikut ditandai sehingga asal variabel mudah dilacak. Pesan error yang sekaligus memuat saran perbaikan merupakan pola umum compiler Rust, sehingga membaca keluaran kompilasi menjadi kebiasaan yang produktif.

Kata kunci mut#

Ketika sebuah variabel memang perlu berubah, tambahkan kata kunci mut di antara let dan nama variabel. Variabel menjadi dapat diubah (mutable) dan menerima penugasan nilai baru berapa kali pun sepanjang tipenya sama.

rust mutabel.rs
fn main() {
    let mut hitung = 0;
    hitung = hitung + 10;
    hitung += 5;
    println!("total hitung: {hitung}");
}
text Keluaran
total hitung: 15

Operator gabungan seperti += meringkas penugasan dan operasi aritmetika menjadi satu baris. Kata kunci mut juga berfungsi sebagai sinyal dokumentasi: pembaca kode langsung mengetahui variabel mana yang berubah di sepanjang program. Karena itu, tambahkan mut hanya pada variabel yang benar-benar berubah supaya sinyal tersebut tetap tajam. Ketika nilai tidak pernah diubah, variabel immutable memberi jaminan kepada pembaca bahwa nilainya tetap dari deklarasi sampai akhir lingkup.

Compiler turut menjaga sinyal ini dari arah sebaliknya. Variabel mut yang tidak pernah diberi nilai baru memicu peringatan variable does not need to be mutable, sehingga kata kunci yang tidak terpakai tetap terlihat dan mudah dibersihkan.

Shadowing#

Shadowing terjadi ketika deklarasi let baru menggunakan nama yang sama dengan variabel sebelumnya. Variabel baru menutupi variabel lama sejak baris deklarasi tersebut, sementara variabel lama tetap menyimpan nilai aslinya di balik nama yang sama.

rust shadowing.rs
fn main() {
    let x = 5;
    let x = x + 1;
    {
        let x = x * 2;
        println!("x di dalam lingkup dalam: {x}");
    }
    println!("x di luar lingkup dalam: {x}");
}
text Keluaran
x di dalam lingkup dalam: 12
x di luar lingkup dalam: 6

Nilai x menjadi 6 setelah shadowing pertama, lalu lingkup dalam menghitung 12 dari nilai tersebut. Setelah kurung kurawal lingkup dalam ditutup, shadowing di dalamnya berakhir dan nama x kembali menunjuk variabel bernilai 6. Keunggulan utama shadowing adalah tipe variabel baru boleh berbeda dari yang lama, sehingga satu nama dapat dipakai ulang untuk tahap pengolahan yang berbeda.

rust bayangan.rs
fn main() {
    let spasi = "   ";
    println!("tipe teks, panjang byte: {}", spasi.len());
    let spasi = spasi.len();
    println!("sekarang bilangan: {spasi}");
}
text Keluaran
tipe teks, panjang byte: 3
sekarang bilangan: 3

Konstanta#

Konstanta dideklarasikan dengan const dan menyerupai variabel immutable, tetapi aturannya lebih ketat. Anotasi tipe wajib ditulis, nilainya harus dapat dihitung saat kompilasi, dan penamaannya memakai huruf besar dengan garis bawah. Konstanta juga dapat dideklarasikan di luar fungsi sehingga berlaku untuk seluruh berkas.

rust konstanta.rs
const MAKS_PESERTA: u32 = 100;

fn main() {
    let peserta = 24;
    let sisa = MAKS_PESERTA - peserta;
    println!("sisa kursi: {sisa}");
}
text Keluaran
sisa kursi: 76

Kata kunci mut tidak berlaku pada konstanta karena nilainya memang tidak pernah berubah. Nilai konstanta juga tidak boleh merupakan hasil pemanggilan fungsi atau nilai yang baru diketahui saat program berjalan, misalnya hasil pembacaan masukan pengguna. Perbedaan penting di antara keduanya dirangkum pada tabel berikut.

AspekVariabel letKonstanta const
Sifat nilaidapat berubah dengan mutselalu tetap
Anotasi tipeopsional, dapat disimpulkanwajib ditulis
Nilai yang diterimanilai apa pun saat program berjalannilai yang diketahui saat kompilasi
Penamaanhuruf kecil bergaris bawahhuruf besar bergaris bawah
Lingkupdari deklarasi sampai akhir lingkuplingkup item, termasuk luar fungsi

Konstanta dapat dideklarasikan di luar fungsi dan dipakai di seluruh berkas, sedangkan variabel let di luar fungsi tidak sah. Ketika sebuah nilai bersifat tetap dan bermakna global, konstanta memberi jaminan yang lebih kuat daripada variabel immutable.

Kesalahan umum#

Menambahkan mut pada semua variabel. Kebiasaan ini menghapus manfaat utama variabel immutable karena penugasan yang tidak disengaja tidak lagi terdeteksi. Tambahkan mut hanya setelah compiler menolak penugasan yang memang disengaja.

Menganggap shadowing sebagai perubahan nilai. Shadowing tidak mengubah isi variabel lama, melainkan membuat variabel baru yang menutupi nama lama. Nilai variabel lama tetap ada dan dapat dipakai lagi begitu lingkup shadowing berakhir, sehingga pola ini bukan pengganti mut untuk memperbarui data secara berkelanjutan. Gunakan shadowing untuk transformasi bertahap yang menghasilkan nilai baru, dan gunakan mut untuk pembaruan nilai yang berlangsung terus-menerus seperti penghitung.

Ringkasan#

  • let membuat variabel yang tipenya disimpulkan compiler dan bersifat immutable secara bawaan.
  • Penugasan ulang variabel immutable menghasilkan error E0384, dengan saran perbaikan berupa penambahan mut.
  • mut mengizinkan perubahan isi variabel dengan tipe yang tetap, sekaligus menjadi penanda niat di dalam kode.
  • Shadowing membuat variabel baru bernama sama, boleh dengan tipe berbeda, dan berlaku sampai akhir lingkupnya.
  • const menuntut anotasi tipe, nilai yang diketahui saat kompilasi, dan tidak dapat dipasangkan mut.

Referensi#