Closures & Iterators di Rust
Closure adalah fungsi anonim yang bisa menangkap variabel dari lingkungan sekitarnya. Digabung dengan iterator, kamu bisa menulis kode pengolah data yang ringkas dan cepat — mirip map/filter/reduce di JavaScript, tapi zero-cost.
Sintaks Closure
let tambah_satu = |x| x + 1;
let hasil = tambah_satu(5); // 6
// Dengan tipe eksplisit dan block
let tambah = |a: i32, b: i32| -> i32 {
a + b
};
println!("{}", tambah(3, 4)); // 7
Capture Environment
let faktor = 10;
let kali_faktor = |x| x * faktor; // capture `faktor` dari luar
println!("{}", kali_faktor(5)); // 50
Fn, FnMut, FnOnce
Rust punya 3 trait closure berdasarkan cara closure memakai environment:
Fn— hanya baca environment (pakai&)FnMut— ubah environment (pakai&mut)FnOnce— consume environment (move), hanya bisa dipanggil sekali
Compiler memilih otomatis — kamu baru perlu tahu saat mendeklarasikan closure sebagai parameter fungsi.
move Keyword
let teks = String::from("halo");
let cetak = move || println!("{}", teks);
// teks sudah di-move ke closure, tidak bisa dipakai di sini
cetak();
move dipakai saat closure harus memiliki data yang di-capture — misalnya saat dipassing ke thread baru.
Iterator Basics
let v = vec![1, 2, 3];
// iter() — borrow &T
for x in v.iter() { println!("{}", x); }
// iter_mut() — borrow &mut T
let mut v = vec![1, 2, 3];
for x in v.iter_mut() { *x *= 2; }
// into_iter() — consume, take ownership
for x in v.into_iter() { println!("{}", x); }
// v tidak bisa dipakai lagi
Iterator Adapters — map, filter, collect
let angka = vec![1, 2, 3, 4, 5];
let kuadrat: Vec<i32> = angka.iter()
.map(|x| x * x)
.collect();
// [1, 4, 9, 16, 25]
let genap: Vec<i32> = angka.iter()
.filter(|&&x| x % 2 == 0)
.copied()
.collect();
// [2, 4]
// Chaining
let total: i32 = angka.iter()
.filter(|&&x| x > 2)
.map(|x| x * 10)
.sum();
// 3*10 + 4*10 + 5*10 = 120
Lazy Evaluation
Iterator di Rust bersifat lazy — adapter seperti map dan filter tidak mengerjakan apa pun sampai ada consuming adapter seperti collect(), sum(), atau for.
let iter = angka.iter().map(|x| x * 2); // belum dikerjakan
let hasil: Vec<i32> = iter.collect(); // baru dikerjakan di sini
for Loop = Iterator
Di bawah kulit, for loop dijabarkan (desugared) menjadi pemanggilan next() pada iterator. Jadi menulis iterator chain sama cepatnya dengan for manual — itulah zero-cost abstraction.
Method Iterator Lain yang Berguna
let v = vec![1, 2, 3, 4, 5];
println!("{}", v.iter().count()); // 5
println!("{:?}", v.iter().max()); // Some(5)
println!("{}", v.iter().any(|&x| x > 3)); // true
println!("{}", v.iter().all(|&x| x > 0)); // true
println!("{:?}", v.iter().find(|&&x| x > 2)); // Some(3)