Pattern Matching ist einer der wichtigsten Sprachmechanismen in Rust, der aus funktionalen Sprachen stammt. Es ermöglicht die deklarative, prägnante und sichere Behandlung komplexer Wertvarianten, auch durch zusätzliche Bedingungen (Guard-Ausdrücke), was Flexibilität und Kontrolle über die Logik gibt.
Ohne Exhaustiveness Checking (Überprüfung der vollständigen Berücksichtigung aller Varianten) kann ein Teil der Leistungsfähigkeit von Pattern Matching fehlerhaft implementiert werden. Zudem kann man ohne Verständnis der Reihenfolge der Zweige und der Guard-Ausdrücke sowohl in der Logik als auch in der Performance Fehler machen.
In Rust überprüft der Compiler, dass alle Varianten eines Enums (oder einfacherer Pattern-Strukturen) behandelt werden, oder dass ein Zweig _ vorhanden ist. Der Zweig kann außerdem durch einen Guard-Ausdruck (if nach dem Pattern) eingeschränkt werden, und nur wenn die Bedingung erfüllt ist, "trifft" er ein. Übrige Varianten werden nicht erfasst. Die Reihenfolge der Zweige ist wichtig: sie werden von oben nach unten überprüft.
Beispielcode:
enum Message { Hello, Data(i32), Quit, } fn handle(msg: Message) -> &'static str { match msg { Data(n) if n > 10 => "Big Data", Data(_) => "Some Data", Hello => "Greet!", Quit => "Bye", } }
Wichtige Merkmale:
Tritt der Zweig mit Guard ein, wenn das Pattern übereinstimmt, aber die Bedingung nicht erfüllt ist?
Nein, in diesem Fall wird zur nächsten passenden Branche gewechselt. Pattern + Guard ist ein atomarer "Filter"; nur wenn beide übereinstimmen, wird der Körper des Zweigs ausgeführt.
Beeinflusst die Reihenfolge der Zweige im Match die Performance?
Ja. Besonders bei einer Vielzahl ähnlicher Patterns mit Guard: Der Compiler überprüft die Zweige von oben nach unten, was die Geschwindigkeit der Überprüfung zur Laufzeit beeinflusst – häufiger vorkommende Werte sollten früher verarbeitet werden.
Kann man Exhaustiveness Checking umgehen, indem man nur den Zweig _ setzt?
Technisch ja — das ist erlaubt, aber es geht Zuverlässigkeit verloren: Wenn der Typ neue Elemente ausschließt (oder hinzufügt), warnt der Compiler nicht vor nicht berücksichtigten Fällen. Es ist besser, immer wichtige Fälle explizit zu behandeln und "_" nur im Extremfall zu verwenden.
Ein Match-Code für ein Enum mit Guard-Ausdrücken, bei dem das Pattern mit Guard zuletzt kommt, aber die meisten Werte direkt über den frühen Zweig _ verarbeitet werden und die notwendige Verarbeitung nie erreicht wird.
Vorteile:
_.Nachteile:
Zuerst werden die häufigsten und wichtigsten Varianten (mit Guard) aufgezählt, dann werden die übrigen exhaustively behandelt — ohne überflüssigen Code in "_".
Vorteile:
Nachteile: