⚡ 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();
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 |
🧠 Diagnostischer Selbst-Check
Überprüfe dein Verständnis von Ownership, Borrowing und Typensicherheit, bevor du die Übung in der Web-IDE bearbeitest.