⚑ Lehrpfad 3: Traits, Generics & Smart Pointer

Rust 11: Closures & Iterator Pipelines

Meistere funktionale Programmierung in Rust: Closures (Fn, FnMut, FnOnce), Custom-Iteratoren und hocheffiziente Zero-Cost Iterator-Pipelines.

πŸ“‚ Dateien dieser Lerneinheit:
πŸ“„ aufgabe.rs (Startercode) πŸ§ͺ test_aufgabe.rs (Tests) πŸ’‘ musterloesung.rs (LΓΆsung) πŸ“– README.md

⚑ 1. Closures & die Trait-Hierarchie (Fn, FnMut, FnOnce)

Ein Closure ist eine anonyme Funktion, die Variablen aus ihrer Umgebung einfangen (capturen) kann. Der Rust-Compiler leitet automatisch das restriktivste Trait ab:

                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                        β”‚    FnOnce    β”‚ (Konsumiert Umgebung / Move, 1x aufrufbar)
                        β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                               β–²
                        β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
                        β”‚    FnMut     β”‚ (VerΓ€ndert Umgebung &mut, mehrfach aufrufbar)
                        β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                               β–²
                        β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
                        β”‚      Fn      β”‚ (Liest Umgebung unverΓ€nderlich &T, nebenlΓ€ufig nutzbar)
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
// 1. Fn: Liest Referenz
let factor = 2;
let double = |x: i32| x * factor;

// 2. FnMut: Mutiert Zustand
let mut count = 0;
let mut inc = || { count += 1; count };

// 3. FnOnce / move: Übernimmt Ownership
let text = String::from("Rust");
let consume = move || println!("Taken: {}", text);

πŸ›‘οΈ 2. Der Iterator Trait & Adapter Pipelines

In Rust sind Iteratoren lazy (trΓ€ge) – Berechnungen finden erst statt, wenn ein Consumer wie .collect(), .sum() oder .fold() die Pipeline konsumiert.

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

// Zero-Cost Pipeline:
let sum_of_even_squares: u64 = (1..=100)
    .filter(|&x| x % 2 == 0)
    .map(|x| x * x)
    .sum();
🏭 Didaktische Analogie: Das Montageband in der Fabrik

Ein Iterator ist wie ein Fließband: .filter() und .map() sind Bearbeitungsstationen am Band. Das Band bewegt sich jedoch kein Stück, bis am Ende der Fertigwaren-EmpfÀnger (.collect()) das Paket anfordert!

πŸ“‘ 3. Cheat-Sheet: Wichtige Iterator-Adapter

Adapter / Consumer Signatur-Beispiel Beschreibung
.map(f) iter.map(|x| x * 2) Transformiert jedes Element 1:1
.filter(p) iter.filter(|x| *x > 10) BehΓ€lt nur Elemente, die dem PrΓ€dikat entsprechen
.fold(init, f) iter.fold(0, |acc, x| acc + x) Aggregiert alle Werte in einen Akkumulator
.collect() iter.collect::<Vec<_>>() Wandelt Iterator in eine konkrete Kollektion um

🎯 Aufgaben & Checkliste in aufgabe.rs

πŸ’» In Web-IDE ΓΆffnen → ← ZurΓΌck zu Rust 10 Weiter zu Rust 12: Smart Pointer →