Zum Inhalt springen

Musterabgleich

enum Location {
Point(i32),
Range(i32, i32)
}
fn main() {
let l: Location = Location::Range(0, 5);
let n = match l {
Location::Point(_) => -1,
Location::Range(_, 5) => 5,
Location::Range(0, _) => 0,
_ => -2
};
println!("{n}");
}

Jedes Match-Muster wird von oben nach unten geprüft. Sowohl das zweite als auch das dritte Muster sind anwendbar, daher wird das zweite verwendet.


Betrachten Sie diese Methode, die für den Typ Option implementiert wurde:

impl<T> Option<T> {
fn unwrap_or(self, other: T) -> T {
match self {
Some(t) => t,
None => other
}
}
}

Welcher Satz beschreibt das Verhalten dieser Funktion am besten?

Diese Funktion “entpackt” die Option, indem sie deren Ownership konsumiert und den darin enthaltenen Wert abruft. Falls jedoch kein Wert existiert, greift sie auf die Rückgabe von other zurück. Dies ist eine echte Funktion in der Standardbibliothek!


#[derive(Debug)]
enum Either {
Left(usize),
Right(String)
}
fn main() {
let x = Either::Right(String::from("Hello world"));
let value = match x {
Either::Left(n) => n,
Either::Right(s) => s.len()
};
println!("{x:?} {value}");
}

Der Match-Arm Either::Right(s) verschiebt das Feld s, daher kann x nicht im println! verwendet werden.


Betrachten Sie diese beiden Implementierungen einer Funktion, um eine vorzeichenlose Zahl zweimal zu dekrementieren.

fn decr_twice_v1(n: u32) -> Option<u32> {
match n {
0 => None,
1 => None,
n2 => Some(n2 - 2)
}
}
fn decr_twice_v2(n: u32) -> Option<u32> {
if n == 0 {
None
} else if n == 1 {
None
} else {
Some(n - 2)
}
}

Die Funktionen haben das gleiche Verhalten für:

Das match und das if erfüllen hier die gleiche Funktion. Ein match ist wie ein spezialisiertes if, das auf Gleichheit des abgeglichenen Objekts prüft.