CodeBlanks Logo Icon CodeBlanks

Iterator fusion

Iterator fusion ile optimizasyon yapmayı öğrenirsin.

Iterator fusion

Zincirlenmiş bağdaştırıcılar ayrı ayrı geçişler yapmaz: her eleman tüm zinciri tek seferde geçer. Derleyici satır içi alma ile zinciri tek bir döngüye "kaynaştırır". Bu, sırayı gözlemleyince açıkça görülür:

let kayit = RefCell::new(Vec::new());
let _ = (1..=3)
    .map(|x| { kayit.borrow_mut().push(format!("m{x}")); x * 2 })
    .filter(|x| { kayit.borrow_mut().push(format!("f{x}")); *x > 2 })
    .count();
// m1 f2 m2 f4 m3 f6 — önce tüm map'ler değil, eleman eleman

Ara koleksiyon oluşmadığı için bellek kullanımı da sabittir.

collect araları

Zincirin ortasına collect koymak kaynaşmayı bozar: tüm elemanlar bir vektöre yazılır, sonra yeniden okunur. Yalnızca gerçekten gerektiğinde (sıralama, birden çok geçiş) ara koleksiyon kullan:

// gereksiz ara vektör
let ara: Vec<_> = v.iter().map(|x| x * 2).collect();
let t: i32 = ara.iter().filter(|x| **x > 2).sum();

// kaynaşmış
let t: i32 = v.iter().map(|x| x * 2).filter(|x| *x > 2).sum();

Uygulama Kaynaşmayı gözle

Yukarıdaki örneği yaz: RefCell<Vec<String>> günlüğüne map içinde mX, filter içinde fX ekle; zinciri count() ile tüket. Günlüğü boşlukla birleştirip yazdır.

Başlangıç kodu

main.rs
use std::cell::RefCell;

fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
use std::cell::RefCell;

fn main() {
    let kayit = RefCell::new(Vec::new());
    let _adet = (1..=3)
        .map(|x| {
            kayit.borrow_mut().push(format!("m{x}"));
            x * 2
        })
        .filter(|x| {
            kayit.borrow_mut().push(format!("f{x}"));
            *x > 2
        })
        .count();
    println!("{}", kayit.borrow().join(" "));
}

Beklenen çıktı

m1 f2 m2 f4 m3 f6

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Neden günlük için <code>RefCell</code> gerekti?

  • Gerekmezdi
  • Thread'ler için
  • İki closure aynı vektörü değiştirmek istiyor; iki &mut aynı anda yakalanamaz Doğru cevap
  • Hız için

Açıklama: Her closure yalnızca &RefCell yakalar; değiştirme çalışma anında, kısa ödünçlerle yapılır.

2 Paylaşılan günlük

Soru
let kayit = ____::new(Vec::new());
// iki closure da kayit.borrow_mut() ile yazar
Cevap
let kayit = RefCell::new(Vec::new());
// iki closure da kayit.borrow_mut() ile yazar

Açıklama: RefCell iki closure'ın aynı vektörü sırayla değiştirmesine izin verir.

3 Zincir ve geçiş sayısı

Kavram Anlamı
map + filter + sum 1 geçiş
map + collect + filter + sum 2 geçiş
sort gerektiren iş Ara koleksiyon şart
take(2) Erken durur

Uzman bölümündeki tüm dersler