Match in Rust
match vergleicht einen Wert mit einer Liste von Mustern (Patterns) und führt den Code des Musters aus, das passt. Wenn du schon mal eine switch-Anweisung benutzt hast: match ist eine deutlich mächtigere Version davon. Und wenn nicht, ist es trotzdem eines der nützlichsten Werkzeuge, die du früh lernen kannst.
Ein einfaches match
Abschnitt betitelt „Ein einfaches match“fn main() { let day = 3;
match day { 1 => println!("Montag"), 2 => println!("Dienstag"), 3 => println!("Mittwoch"), 4 => println!("Donnerstag"), 5 => println!("Freitag"), _ => println!("Wochenende"), }}Ausgabe:
MittwochJede Zeile der Form Muster => Code heißt Arm (Zweig). Der _ ist ein Catch-all (Auffangmuster): Er passt auf alles, was weiter oben nicht aufgeführt ist. match verlangt, dass jeder mögliche Wert behandelt wird. Deshalb steht _ meistens am Ende und deckt „alles andere“ ab.
Mehrere Werte auf einmal abgleichen
Abschnitt betitelt „Mehrere Werte auf einmal abgleichen“Mit | fasst du mehrere Werte in einem Arm zusammen:
fn main() { let day = 6;
match day { 1 | 2 | 3 | 4 | 5 => println!("Werktag"), 6 | 7 => println!("Wochenende"), _ => println!("Kein gültiger Tag"), }}Einen Bereich abgleichen
Abschnitt betitelt „Einen Bereich abgleichen“Bei Zahlen kannst du mit ..= einen ganzen Bereich abgleichen:
fn main() { let score = 85;
match score { 90..=100 => println!("A"), 75..=89 => println!("B"), 60..=74 => println!("C"), _ => println!("F"), }}match als Ausdruck
Abschnitt betitelt „match als Ausdruck“Genau wie if kann auch match einen Wert liefern:
fn main() { let day = 6;
let kind = match day { 1 | 2 | 3 | 4 | 5 => "Werktag", 6 | 7 => "Wochenende", _ => "unbekannt", };
println!("{kind}");}Text und Zeichen abgleichen
Abschnitt betitelt „Text und Zeichen abgleichen“match ist nicht nur für Zahlen da. Es funktioniert auch mit String-Slices (&str) und mit Zeichen. Zeichenbereiche wie 'a'..='z' funktionieren genau wie Zahlenbereiche:
fn main() { let command = "stop"; match command { "start" => println!("Starte ..."), "stop" | "quit" => println!("Halte an."), _ => println!("Unbekannter Befehl: {command}"), }
let letter = 'k'; let kind = match letter { 'a' | 'e' | 'i' | 'o' | 'u' => "ein Vokal", 'a'..='z' => "ein Konsonant", '0'..='9' => "eine Ziffer", _ => "etwas anderes", }; println!("'{letter}' ist {kind}");
let name = String::from("Ferris"); match name.as_str() { "Ferris" => println!("Hallo, Krabbe!"), _ => println!("Hallo, {name}!"), }}Ausgabe:
Halte an.'k' ist ein KonsonantHallo, Krabbe!Zwei Dinge fallen hier auf:
- Die Reihenfolge zählt.
'a'liegt auch in'a'..='z', aber der Vokal-Arm kommt zuerst. Vokale erreichen den Konsonanten-Arm also nie. Rust nimmt immer den ersten Arm, der passt. - Ein
Stringbraucht.as_str(). Text in Anführungszeichen wie"Ferris"ist ein&str. Wenn du einenStringdirekt damit abgleichst, bricht Rust miterror[E0308]: mismatched types ... expected String, found &strab – die Typen passen nicht zusammen..as_str()liefert dir eine&str-Ansicht desString, mit der die Muster vergleichen können. (Den Unterschied zwischen beiden erklärt die Seite Strings.)
Der Abgleich unterscheidet Groß- und Kleinschreibung: "Stop" passt nicht auf "stop". Kommt der Text von einem Benutzer, ist ein üblicher Trick, auf input.to_lowercase().as_str() abzugleichen.
match oder if/else?
Abschnitt betitelt „match oder if/else?“Für einfache Ja/Nein-Prüfungen funktioniert beides. Sobald du aber mehr als zwei oder drei Möglichkeiten hast, ist match im Vorteil: Es liest sich besser als eine lange Kette aus else if, und der Compiler prüft, ob du jeden Fall abgedeckt hast. Für eine einzelne Ja/Nein-Bedingung bleibt if/else das richtige Werkzeug.
Übungen
Abschnitt betitelt „Übungen“1. Tage im Monat
Abschnitt betitelt „1. Tage im Monat“Speichere eine Monatszahl month (2). Berechne mit match als Ausdruck, wie viele Tage der Monat hat (Schaltjahre ignorierst du), und gib Monat 2 hat 28 Tage aus. Tipp: Die Monate 1, 3, 5, 7, 8, 10 und 12 haben 31 Tage. Fasse sie mit | in einem Arm zusammen.
Lösung anzeigen
fn main() { let month = 2;
let days = match month { 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, 4 | 6 | 9 | 11 => 30, 2 => 28, _ => 0, // kein echter Monat };
println!("Monat {month} hat {days} Tage");}Ausgabe:
Monat 2 hat 28 Tage2. HTTP-Statuscodes
Abschnitt betitelt „2. HTTP-Statuscodes“Webserver antworten mit einer Zahl. Mach aus einem code eine kurze Bedeutung: 200 ist "OK", 404 ist "Not Found", jeder andere Code von 400 bis 499 ist "Client-Fehler", 500 bis 599 ist "Server-Fehler", und alles andere ist "Unbekannt". Probier es mit 503 aus. Tipp: Setz den genauen 404-Arm über den Bereich 400..=499, sonst wird er nie erreicht.
Lösung anzeigen
fn main() { let code = 503;
let meaning = match code { 200 => "OK", 404 => "Not Found", // muss vor dem Bereich 400..=499 stehen 400..=499 => "Client-Fehler", 500..=599 => "Server-Fehler", _ => "Unbekannt", };
println!("{code}: {meaning}");}Ausgabe:
503: Server-FehlerZusammenfassung
Abschnitt betitelt „Zusammenfassung“matchvergleicht einen Wert mit Mustern und führt den passenden Arm aus.- Jeder mögliche Wert muss behandelt werden – nimm
_als Catch-all. - Mit
|kombinierst du Werte, mit..=gleichst du einen Bereich ab. - Auch
&str-Text undchar-Werte lassen sich abgleichen; für einenStringnimmst du.as_str(). - Wie
ifkannst dumatchals Ausdruck verwenden, der einen Wert liefert.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Was bewirkt das Muster _ in einem match-Ausdruck?
2. Was passiert, wenn ein match-Ausdruck nicht jeden möglichen Wert behandelt und keinen _-Arm hat?
3. Wie gleichst du mehrere Werte wie 1, 2 oder 3 in einem einzigen Arm ab?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- Das Kontrollflusskonstrukt match – Das Rust-Buch: das offizielle Kapitel, das
matchauch mit Enums undOptionzeigt. - match – Rust by Example (auf Englisch): ein kompaktes, lauffähiges Beispiel mit Werten,
|, Bereichen und_. - Range patterns – The Rust Reference (auf Englisch): welche Typen und Bereichsformen du in einem Muster genau verwenden kannst.
- Match expressions – The Rust Reference (auf Englisch): die genauen Regeln für Arme, Guards und wie ein
matchseinen Wert liefert.