Lewati ke konten

Option di Rust

Rust tidak punya null. Kalau sebuah nilai mungkin tidak ada, hal itu dinyatakan langsung di tipenya dengan Option. Awalnya memang terasa seperti formalitas tambahan, tapi cara ini menutup satu kategori bug sepenuhnya: “null reference”, yang sudah menyebabkan crash tak terhitung jumlahnya di bahasa lain.

Option adalah sebuah enum dengan dua varian:

enum Option<T> {
Some(T), // ada nilainya
None, // tidak ada nilai
}

Sebenarnya kamu sudah pernah melihatnya: .get() pada vektor dan .get() pada HashMap sama-sama mengembalikan Option.

fn main() {
let has_value: Option<i32> = Some(5);
let no_value: Option<i32> = None;
println!("{:?}", has_value);
println!("{:?}", no_value);
}

Output:

Some(5)
None
▶ Coba sendiri

Cara aman untuk mengambil nilainya adalah dengan match. Rust memaksamu menangani kedua kemungkinan, jadi kamu tidak mungkin tidak sengaja melupakan kasus “tidak ada”:

fn main() {
let age: Option<i32> = Some(30);
match age {
Some(value) => println!("Umurnya {value}"),
None => println!("Umur tidak diisi"),
}
}
▶ Coba sendiri
fn find_user(id: u32) -> Option<&'static str> {
if id == 1 {
Some("Alice")
} else {
None
}
}
fn main() {
match find_user(1) {
Some(name) => println!("Ketemu: {name}"),
None => println!("User tidak ditemukan"),
}
match find_user(99) {
Some(name) => println!("Ketemu: {name}"),
None => println!("User tidak ditemukan"),
}
}

Output:

Ketemu: Alice
User tidak ditemukan
▶ Coba sendiri

Alih-alih mengembalikan null atau melempar exception saat user tidak ditemukan, tipe kembalian fungsinya sendiri sudah memberi tahu setiap pemanggil bahwa “fungsi ini mungkin tidak menemukan apa-apa”. Dan compiler tidak akan membiarkan mereka mengabaikan kemungkinan itu.

Untuk kasus sederhana, match lengkap bisa terasa berlebihan. Ada beberapa jalan pintas:

fn main() {
let age: Option<i32> = None;
let value = age.unwrap_or(0); // pakai 0 sebagai cadangan kalau tidak ada nilai
println!("{value}");
}
▶ Coba sendiri

Ada juga .unwrap(), yang langsung memberimu nilainya, tapi akan panic (crash) kalau isinya None:

let age: Option<i32> = Some(30);
let value = age.unwrap(); // aman di sini, karena age berisi Some

Tulis fn first_even(numbers: &[i32]) -> Option<i32> yang mengembalikan bilangan genap pertama di dalam slice, atau None kalau tidak ada. Cetak hasilnya untuk [3, 7, 8, 10] dengan match, dan untuk [1, 3, 5] dengan .unwrap_or(0). Petunjuk: lakukan perulangan pada slice dan return Some(n) begitu n % 2 == 0; setelah perulangan selesai, kembalikan None.

Lihat solusi
fn first_even(numbers: &[i32]) -> Option<i32> {
for &n in numbers {
if n % 2 == 0 {
return Some(n);
}
}
None
}
fn main() {
match first_even(&[3, 7, 8, 10]) {
Some(n) => println!("Genap pertama: {n}"),
None => println!("Tidak ada bilangan genap"),
}
let fallback = first_even(&[1, 3, 5]).unwrap_or(0);
println!("Dengan nilai cadangan: {fallback}");
}

Output:

Genap pertama: 8
Dengan nilai cadangan: 0
▶ Coba sendiri

Buat sebuah HashMap berisi pengaturan yang hanya memuat "volume" dengan nilai 80. Lalu lakukan perulangan pada key "volume" dan "kecerahan", dan cetak nilainya kalau ada, atau pesan “belum diatur” kalau tidak ada. Petunjuk: .get(key) pada HashMap mengembalikan Option, jadi kamu bisa langsung melakukan match padanya.

Lihat solusi
use std::collections::HashMap;
fn main() {
let mut settings = HashMap::new();
settings.insert("volume", 80);
for key in ["volume", "kecerahan"] {
match settings.get(key) {
Some(value) => println!("{key} = {value}"),
None => println!("{key} belum diatur"),
}
}
}

Output:

volume = 80
kecerahan belum diatur
▶ Coba sendiri
  • Option<T> mewakili nilai yang mungkin ada, mungkin juga tidak. Rust tidak punya null.
  • Some(value) berisi sesuatu; None berarti tidak ada apa-apa.
  • match adalah cara aman untuk menangani kedua kasus; compiler tidak akan membiarkanmu melupakan salah satunya.
  • .unwrap_or(default) memberimu nilai cadangan; .unwrap() akan panic kalau nilainya None, jadi pakailah seperlunya.

Kuis singkat

1. Apa yang dipakai Rust sebagai pengganti null untuk nilai yang mungkin tidak ada?

2. Apa yang terjadi kalau kamu memanggil .unwrap() pada nilai None?

3. Apa yang dilakukan age.unwrap_or(0) kalau age bernilai None?

4. Kenapa match dianggap cara aman untuk mengambil nilai dari Option?

5. Method mana yang disebut di halaman ini yang sudah mengembalikan Option?

Skor: 0 / 5