Halo teman-teman semuanya, pada artikel sebelumnya kita sudah mempelajari tentang collection di Rust, yaitu Vector
, HashMap
, dan HashSet
. Kita belajar bagaimana menyimpan data dalam daftar, pasangan key-value, maupun sekumpulan nilai unik. Collection ini menjadi fondasi untuk menyimpan data yang lebih kompleks di Rust.
Namun, hanya menyimpan data saja tidak cukup. Sering kali kita ingin melakukan operasi pada data tersebut: membaca satu per satu, memprosesnya, memfilter sesuai kondisi tertentu, atau mengubahnya menjadi bentuk lain. Di Rust, cara yang paling powerful untuk melakukan hal itu adalah dengan iterator.
Iterator adalah sebuah objek yang menyediakan cara untuk mengakses elemen dalam sebuah koleksi satu per satu. Konsep ini bukan hanya untuk perulangan, tetapi juga untuk transformasi data yang lebih efisien, karena Rust mendukung lazy evaluation (eksekusi ditunda sampai benar-benar dibutuhkan).
Membuat Iterator
Hampir semua collection di Rust bisa diubah menjadi iterator dengan method .iter()
.
fn main() {
let angka = vec![10, 20, 30];
for n in angka.iter() {
println!("Angka: {}", n);
}
}
Method .iter()
menghasilkan iterator yang mengembalikan reference ke tiap elemen.
Iterator Mutable
Jika kita ingin mengubah isi collection lewat iterator, gunakan .iter_mut()
.
fn main() {
let mut angka = vec![1, 2, 3];
for n in angka.iter_mut() {
*n *= 2; // kalikan setiap elemen dengan 2
}
println!("{:?}", angka);
}
Mengonsumsi Iterator
Ada banyak method bawaan iterator di Rust. Beberapa contoh yang paling sering digunakan:
.next()
→ mengambil elemen berikutnya secara manual.
.map()
→ mengubah setiap elemen.
.filter()
→ menyaring elemen sesuai kondisi.
.collect()
→ mengubah iterator menjadi collection baru.
.sum()
→ menjumlahkan semua elemen.
fn main() {
let angka = vec![1, 2, 3, 4, 5];
// jumlah total
let total: i32 = angka.iter().sum();
println!("Total: {}", total);
// map: kalikan semua angka dengan 2
let hasil: Vec<i32> = angka.iter().map(|x| x * 2).collect();
println!("Hasil map: {:?}", hasil);
// filter: hanya ambil angka genap
let genap: Vec<&i32> = angka.iter().filter(|&&x| x % 2 == 0).collect();
println!("Angka genap: {:?}", genap);
}
Iterator dengan next()
Kita juga bisa mengakses iterator secara manual dengan next()
.
fn main() {
let mut iter = vec![100, 200, 300].iter();
println!("{:?}", iter.next()); // Some(100)
println!("{:?}", iter.next()); // Some(200)
println!("{:?}", iter.next()); // Some(300)
println!("{:?}", iter.next()); // None
}
Some
berarti ada elemen, sedangkan None
berarti iterator sudah habis.
Lazy Evaluation
Penting untuk dipahami bahwa iterator di Rust bersifat lazy. Artinya, method seperti .map()
atau .filter()
tidak langsung dijalankan, tetapi baru dieksekusi saat hasilnya dikonsumsi (misalnya dengan collect()
atau for
).
fn main() {
let angka = vec![1, 2, 3];
let iter = angka.iter().map(|x| {
println!("Proses {}", x);
x * 2
});
// tidak ada output karena iter belum dikonsumsi
let hasil: Vec<i32> = iter.collect();
println!("Hasil: {:?}", hasil);
}
Outputnya menunjukkan bahwa proses baru dilakukan saat collect()
dipanggil.
Kesimpulan
Pada artikel ini kita sudah belajar tentang iterator di Rust. Kita melihat bagaimana membuat iterator dengan .iter()
dan .iter_mut()
, bagaimana mengonsumsi iterator dengan method seperti .map()
, .filter()
, .collect()
, dan .sum()
, serta bagaimana iterator bersifat lazy sehingga efisien.
Iterator adalah salah satu fitur yang membuat Rust sangat powerful dalam memproses data collection dengan aman dan cepat. Pada artikel berikutnya, kita akan membahas tentang Closure di Rust, yaitu fungsi anonim yang sering dipakai bersama iterator.
Terima Kasih