Mutability (changing)
Di saat Anda mendeklarasikan sebuah variabel dengan let
, maka secara default (otomatis), ia akan immutable (tidak bisa diubah).
Pada contoh ini, codenya tidak akan berjalan:
fn main() { let my_number = 8; my_number = 10; // ⚠️ }
Compiler akan mengatakan: error[E0384]: cannot assign twice to immutable variable my_number
. Ini dikarenakan variabelnya adalah immutable jika kita hanya menulis let
.
Tapi terkadang kita ingin mengubah value dari variabel yang kita gunakan. Untuk membuat variabel yang bisa kita ubah valuenya, tambahkan mut
setelah let
:
fn main() { let mut my_number = 8; my_number = 10; }
Dan sekarang programnya menjadi tidak ada masalah.
Namun, Anda tidak bisa mengganti typenya. Meskipun menggunakan mut
, Rust tidak akan memperbolehkan Anda untuk melakukan pergantian type. Sebagai contoh, code di bawah ini tidak bisa dijalankan:
fn main() { let mut my_variable = 8; // my_variable menggunakan type i32. Dan itu tidak dapat diubah my_variable = "Hello, world!"; // ⚠️ }
Anda akan melihat pesan "expected" dari compiler: expected integer, found &str
. &str
adalah sebuah type string yang sebentar lagi akan kita pelajari.
Shadowing
Shadowing artinya menggunakan let
untuk mendeklarasikan variabel baru dengan nama yang sama sebagai variabel yang berbeda. Hal ini terlihat mirip seperti mutability (bisa diubah), tapi padahal ia adalah hal yang sama sekali berbeda. Beginilah bentuk dari Shadowing:
fn main() { let my_number = 8; // Typenya adalah i32 println!("{}", my_number); // cetak 8 let my_number = 9.2; // ini bertype f64 dengan nama yang sama. Tapi ini bukan merupakan variabel my_number yang pertama. - ini sama sekali berbeda! println!("{}", my_number) // cetak 9.2 }
Kita bisa menyebutnya sebagai "shadowed"/"menyembunyikan" my_number
dengan sebuah "let binding" yang baru.
Lantas, apakah my_number
yang ada di awal menjadi hangus/hancur? Tidak, namun di saat kita memanggil my_number
, kita sekarang mendapatkan my_number
yang bertype f64
. Dan karena mereka berada pada scope block yang sama ({}
yang sama), kita jadi sama sekali tidak bisa lagi melihat my_number
yang pertama.
Tapi jika mereka ada di block yang berbeda, kita bisa melihat keduanya. Contohnya:
fn main() { let my_number = 8; // Typenya adalah i32 println!("{}", my_number); // cetak 8 { let my_number = 9.2; // Typenya adalah f64. It is not my_number (yang berada di awal)- keduanya berbeda! println!("{}", my_number) // Cetak 9.2 // Tapi "shadowed variable" my_number telah hangus dibagian ini. // my_number yang pertama masih hidup! } println!("{}", my_number); // cetak 8 }
Jadi, di saat Anda men-shadow sebuah variabel, Anda tidak menghancurkannya it. Lebih tepatnya, Anda memblocknya.
Jadi, apa sebenarnya kegunaan dari shadowing? Shadowing tepat digunakan apabila Anda perlu untuk mengubah sebuah variabel lebih sering. Bayangkan dimana Anda ingin melakukan banyak operasi matematis menggunakan variabel:
fn times_two(number: i32) -> i32 { number * 2 } fn main() { let final_number = { let y = 10; let x = 9; // mula-mula, x bernilai 9 let x = times_two(x); // x di-shadow dengan nilai yang baru: 18 let x = x + y; // x di-shadow lagi dengan nilai baru: 28 x // me-return x: final_number sekarang bernilai x }; println!("The number is now: {}", final_number) }
Tanpa shadowing, kita harus memikirkan nama yang berbeda-beda, meskipun kita tidak peduli dengan x:
fn times_two(number: i32) -> i32 { number * 2 } fn main() { // Anggaplkah kita menggunakan Rust tanpa shadowing let final_number = { let y = 10; let x = 9; // mula-mula, x bernilai 9 let x_twice = times_two(x); // nama kedua untuk x let x_twice_and_y = x_twice + y; // nama ketiga x! x_twice_and_y // sayang sekali kita tidak menggunakan shadowing - padahal kita bisa saja langsung menggunakan x jika kita menggunakan shadowing }; println!("The number is now: {}", final_number) }
Intinya, kita bisa melihat shadowing di Rust pada kasus ini. Ia digunakan dimana kita ingin secara cepat mengambil sebuah variabel, melakukan operasi pada variabel tersebut, dan melakukan operasi lanjutan lainnya lagi. Dan Anda biasanya menggunakan shadowing ini untuk quick variable yang dimana sebenarnya tidak begitu Anda pedulikan penamaannya.