v3.1.0Kontrollfluss
Pattern Matching
Das match Statement ist wie ein switch auf Steroiden - mit Exhaustiveness Check, Guards und Destructuring.
Grundlegendes Matching
match prüft einen Wert gegen eine Reihe von Mustern und führt den ersten passenden Zweig aus. Der Compiler prüft bei Enums, ob alle Fälle abgedeckt sind (Exhaustiveness Check).
let status = 404;
match status {
200 => log.info("Alles OK"),
404 => log.error("Nicht gefunden"),
500 => log.error("Server Fehler"),
_ => log.warn("Unbekannter Status") // Wildcard fängt alles andere
}Pattern Types
Exakte Werte matchen:
match value {
"hello" => log.info("Greeting"),
42 => log.info("The Answer"),
true => log.info("Truthy"),
_ => log.info("Something else")
}Guards (Zusätzliche Bedingungen)
Guards erlauben zusätzliche if-Bedingungen an Pattern:
let value = Result::Ok(42);
match value {
Ok(x) if x > 0 => "positive",
Ok(x) if x < 0 => "negative",
Ok(0) => "zero",
Err(e) => "error: " + e,
_ => "unknown"
}
// Komplexere Guards
match user {
User { age, role: "admin" } if age >= 18 => {
log.info("Volljähriger Admin");
},
User { age } if age < 13 => {
log.info("Kind");
},
User { name } => {
log.info("Normaler User: " + name);
}
}Enum Matching
Pattern Matching ist besonders mächtig mit Enums (Algebraic Data Types):
enum Status {
Idle,
Running(number), // Fortschritt in Prozent
Error(string)
}
fn checkStatus(s: Status) {
match s {
Status.Idle => log.info("System ist bereit."),
Status.Running(p) => log.info("Verarbeitung: " + p + "%"),
Status.Error(msg) => log.error("Kritischer Fehler: " + msg),
}
}
// Payment Enum
enum PaymentMethod {
Cash,
CreditCard(string), // Kartennummer
PayPal(string), // Email
}
fn processPayment(method: PaymentMethod) {
match method {
PaymentMethod.Cash => {
log.info("Barzahlung empfangen");
},
PaymentMethod.CreditCard(num) => {
log.info("Karte wird belastet: ****" + num.slice(-4));
},
PaymentMethod.PayPal(email) => {
log.info("PayPal-Zahlung an: " + email);
}
}
}Result & Optional Matching
// Result Matching
let result = parseNumber("42");
match result {
Ok(value) => log.info("Parsed: " + value),
Err(error) => log.error("Parse Error: " + error)
}
// Optional Matching
let user = findUser("123");
match user {
Some(u) => log.info("Gefunden: " + u.name),
None => log.warn("User nicht gefunden")
}
// Kombiniert mit Guards
match fetchData(url) {
Ok(data) if data.length() > 0 => processData(data),
Ok(_) => log.warn("Leere Antwort"),
Err(e) if e.code == 404 => log.info("Nicht gefunden"),
Err(e) => log.error("Fehler: " + e.message)
}Vorteile gegenüber If-Else
Sicherheit
Der Compiler warnt, wenn ein Fall vergessen wurde (Exhaustiveness)
Lesbarkeit
Klare Strukturierung von komplexen Verzweigungen
Performance
Intern als effiziente Sprungtabelle (Jump Table) in Rust implementiert
Best Practices
Wildcard zuletzt
Setze _ immer als letzten Arm
Spezifisch zu allgemein
Ordne Patterns von spezifisch nach allgemein
Guards sparsam
Verwende Guards nur wenn nötig
Destructure nur was du brauchst
Ignoriere ungenutzte Felder mit _