Option<T> ist Rusts Antwort auf das Null-Problem. In Sprachen wie Java, C, JavaScript ist jede Referenz potenziell null — und vergessenes Null-Check ist eine der häufigsten Bug-Quellen überhaupt (Tony Hoare nannte es seinen „Billion-Dollar-Mistake"). Rust eliminiert das Problem komplett: ein Wert ist entweder Some(T) (vorhanden) oder None (nicht vorhanden). Der Compiler verlangt, dass du beide Fälle behandelst, bevor du auf den Wert zugreifst. Dieser Artikel zeigt das vollständige API von Option, die wichtigsten Patterns und macht klar, warum diese eine Typ-Idee viele klassische Bugs eliminiert.

Hinweis: Option<T> ist ein generischer Typ — <T> steht für „irgendein Inhalts-Typ". Generics als Mechanismus werden im Generics-Kapitel ausführlich erklärt; hier nutzen wir Option einfach als fertigen Stdlib-Typ und vertrauen darauf, dass Option<i32>, Option<String> etc. für den jeweiligen Inhaltstyp das tun, was man erwartet.

Definition

Option<T> ist ein einfaches Stdlib-Enum:

Rust Stdlib-Definition
// Aus der Stdlib (vereinfacht):
pub enum Option<T> {
    None,
    Some(T),
}

Beide Varianten sind so wichtig, dass sie im Prelude sind — du kannst Some(...) und None ohne Option::-Präfix nutzen.

Rust Verwendung
fn main() {
    let a: Option<i32> = Some(42);
    let b: Option<i32> = None;
    println!("{a:?} {b:?}");        // Some(42) None
}

Niche-Optimization

Eine besondere Eigenheit: für viele Typen ist Option<T> genauso groß wie T selbst:

Rust Niche-Optimization
use std::mem::size_of;

fn main() {
    println!("{}", size_of::<&i32>());                    // 8
    println!("{}", size_of::<Option<&i32>>());            // 8 — gleich!
    println!("{}", size_of::<Box<i32>>());                 // 8
    println!("{}", size_of::<Option<Box<i32>>>());         // 8 — gleich!
}

&T und Box<T> haben den Null-Pointer nicht als legalen Wert. Der Compiler nutzt das 0x0...0-Pattern als None-Marker. Damit ist Option<&T> syntaktisch typsicher und im Speicher identisch zu einem nullable Pointer in C.

Pattern-Matching auf Option

Rust match
fn beschreibe(o: Option<i32>) -> String {
    match o {
        Some(n) => format!("Wert: {n}"),
        None => "kein Wert".to_string(),
    }
}

fn main() {
    println!("{}", beschreibe(Some(42)));     // "Wert: 42"
    println!("{}", beschreibe(None));         // "kein Wert"
}

Klassisches match mit beiden Varianten. Der Compiler verlangt beide Branches.

if let — kompakter

Rust if let
fn drucke_wenn_da(o: Option<i32>) {
    if let Some(n) = o {
        println!("{n}");
    }
    // None-Fall wird ignoriert
}

Wenn nur der Some-Fall interessiert: if let. Mehr im if-let-Artikel.

Das wichtigste API

unwrap — Wert oder Panic

Rust unwrap
fn main() {
    let o = Some(42);
    let n = o.unwrap();         // 42
    // None.unwrap();           // Panic — „called Option::unwrap on a None value"
}

unwrap() ist die einfachste Form, an den inneren Wert zu kommen: wenn Some(x) vorliegt, gibt sie x zurück; wenn None, panickt sie mit der Standard-Nachricht „called Option::unwrap on a None value".

Wann ist unwrap angemessen? In drei Situationen: in Tests, wo ein Panic eine ehrliche Aussage über einen Test-Bug ist; in Prototypen und Skripten, wo Robustheit egal ist und Schnelligkeit zählt; und in Code, wo None beweisbar unmöglich ist (etwa vec.first().unwrap() direkt nach einer len() > 0-Prüfung). In Production-Code, wo None ein erwarteter Zustand sein könnte, ist unwrap ein potentieller Crash und solltest durch sicherere Methoden ersetzt werden.

expect — Wert oder Panic mit Message

Rust expect
fn main() {
    let o: Option<i32> = std::env::var("PORT").ok().and_then(|s| s.parse().ok());
    let port = o.expect("PORT muss gesetzt sein und u32 sein");
    println!("{port}");
}

expect("nachricht") ist die idiomatischere Variante von unwrap, wenn du wirklich auf einen Wert bestehst. Statt einer generischen Fehler-Nachricht bekommst du eine selbst formulierte Begründung in der Panic-Ausgabe — was beim Debuggen Gold wert ist.

Die Konvention für die Nachricht: erkläre, warum None unmöglich sein sollte, nicht was schiefging. „PORT muss gesetzt sein und u32 sein" sagt zukünftigen Lesern: „der Entwickler hier hat die Annahme getroffen, dass PORT in der Umgebung definiert ist". Wenn das doch nicht stimmt, ist die Panic-Nachricht direkt der Bug-Report.

unwrap_or — Default

Rust unwrap_or
fn main() {
    let o: Option<i32> = None;
    let n = o.unwrap_or(0);     // 0
    assert_eq!(n, 0);

    let o2 = Some(42);
    let m = o2.unwrap_or(0);    // 42
    assert_eq!(m, 42);
}

unwrap_or(default) ist die sichere Variante: bei Some(x) gibt sie x zurück, bei None den übergebenen Default. Kein Panic, kein Pattern-Match — eine einzige saubere Zeile.

Wichtig zu wissen: der Default-Wert wird sofort ausgewertet, egal ob die Option Some oder None ist. Bei billigen Defaults (Konstanten, primitive Werte) ist das egal; bei teuren Defaults (etwa unwrap_or(berechne_default())) wäre die Funktion bei jedem Aufruf ausgeführt — auch wenn das Ergebnis dann verworfen wird. Für teure Defaults gibt es die unwrap_or_else-Variante.

unwrap_or_else — lazy Default

Rust unwrap_or_else
fn main() {
    let o: Option<String> = None;
    let s = o.unwrap_or_else(|| {
        // teure Berechnung — nur ausgeführt bei None
        std::env::var("DEFAULT").unwrap_or_else(|_| "unbekannt".into())
    });
    println!("{s}");
}

unwrap_or_else(closure) ist die lazy Variante: die Closure wird nur dann aufgerufen, wenn die Option tatsächlich None ist. Bei Some(x) passiert nichts mit der Closure — sie wird komplett übersprungen.

Das ist wichtig bei teuren Defaults: eine Environment-Variable lesen, eine Datei öffnen, einen API-Call machen, einen neuen Vec allozieren. Bei unwrap_or(berechne_teuer()) läuft die Berechnung immer; bei unwrap_or_else(|| berechne_teuer()) nur bei Bedarf. Performance-kritisch bei häufig aufgerufenen Funktionen.

Eine verwandte Variante ist unwrap_or_default(), die Default::default() als Fallback nutzt. Sie passt für Standard-Typen, die einen sinnvollen Default haben — String::default() gibt "", Vec::default() gibt einen leeren Vec, i32::default() gibt 0.

unwrap_or_default

Rust unwrap_or_default
fn main() {
    let o: Option<String> = None;
    let s = o.unwrap_or_default();      // ""
    assert_eq!(s, "");

    let o2: Option<i32> = None;
    let n = o2.unwrap_or_default();     // 0
    assert_eq!(n, 0);
}

Default via Default-Trait. Funktioniert für alle Typen, die Default implementieren.

Transformationen

map — auf den Wert anwenden

Rust map
fn main() {
    let o = Some(5);
    let m = o.map(|n| n * 2);        // Some(10)
    assert_eq!(m, Some(10));

    let leer: Option<i32> = None;
    let leer2 = leer.map(|n| n * 2); // None — Closure läuft nicht
    assert_eq!(leer2, None);
}

map ist die Standard-Operation für „transformiere den inneren Wert, falls vorhanden". Bei Some(x) wird die Closure auf x angewendet und das Ergebnis als Some(y) zurückgegeben. Bei None passiert nichts — die Closure läuft gar nicht, und das Ergebnis ist wieder None.

Damit kannst du Transformationen über eine ganze Kette führen, ohne in jedem Schritt auf None zu prüfen. o.map(f).map(g).map(h) läuft entweder vollständig durch (bei Some) oder bleibt bei None. Das ist eines der klassischen funktionalen Patterns aus der Welt von Haskell, ML und Scala — und in Rust völlig idiomatisch.

and_then (flat_map)

Rust and_then
fn parse_zahl(s: &str) -> Option<i32> {
    s.parse().ok()
}

fn verdopple(n: i32) -> Option<i32> {
    if n < 0 { None } else { Some(n * 2) }
}

fn main() {
    let r = Some("5").and_then(|s| parse_zahl(s)).and_then(verdopple);
    assert_eq!(r, Some(10));

    let r2 = Some("abc").and_then(|s| parse_zahl(s)).and_then(verdopple);
    assert_eq!(r2, None);
}

and_then ist der mächtige Bruder von map: er erlaubt verkettete fallible Operationen. Wo map eine Closure mit Rückgabe U nimmt (und in Option<U> wickelt), nimmt and_then eine Closure mit Rückgabe Option<U> und gibt direkt diese zurück — kein zusätzliches Wickeln.

Damit kannst du mehrere Operationen verketten, die jeweils scheitern können. Im Beispiel: erst parse_zahl (kann scheitern, wenn der String keine Zahl ist), dann verdopple (kann scheitern bei negativen Werten). Wenn irgendeine in der Kette None liefert, propagiert das automatisch durch — die folgenden Closures laufen nicht. Das Ergebnis ist eine flache Option<i32>, keine verschachtelte Option<Option<Option<i32>>>.

Dieses Pattern ist in funktionalen Sprachen unter dem Namen flatMap oder bind bekannt — es ist die Monad-Operation für die Option-Monade. Wer das mentale Modell hat, schreibt sehr klare, kompakte fallible Code-Ketten.

filter — bedingt auf None setzen

Rust filter
fn main() {
    let o = Some(42);
    let gerade = o.filter(|&n| n % 2 == 0);     // Some(42)
    let ungerade = Some(43).filter(|&n| n % 2 == 0);    // None
    assert_eq!(gerade, Some(42));
    assert_eq!(ungerade, None);
}

filter macht aus Some(v) ein None, wenn das Prädikat false liefert.

ok_or — zu Result konvertieren

Rust ok_or
fn main() {
    let o: Option<i32> = Some(42);
    let r: Result<i32, &str> = o.ok_or("kein Wert");
    assert_eq!(r, Ok(42));

    let n: Option<i32> = None;
    let r2: Result<i32, &str> = n.ok_or("kein Wert");
    assert_eq!(r2, Err("kein Wert"));
}

ok_or ist der Brücken-Operator zwischen Option und Result. Aus Some(x) wird Ok(x), aus None wird Err(err) mit dem übergebenen Fehler-Wert. Sehr nützlich an Stellen, wo du eine optional-typisierte API in eine error-typisierte API überführen willst.

Das passiert oft an API-Grenzen: deine interne Logik arbeitet mit Option, deine öffentliche Funktion soll aber Result zurückgeben, weil Aufrufer einen aussagekräftigen Fehler erwarten. value.ok_or("nicht gefunden")? macht aus „optionaler Lookup" einen „Fehler mit Kontext" in einer Zeile, kombiniert mit dem ?-Operator. Analog gibt es ok_or_else(closure) für lazy Error-Konstruktion.

Der ?-Operator auf Option

Der ?-Operator funktioniert in Funktionen, die Option zurückgeben — bei None macht er ein early-return:

Rust ? auf Option
fn ersten_buchstaben(s: &str) -> Option<char> {
    let erstes_wort = s.split_whitespace().next()?;     // None → return None
    erstes_wort.chars().next()                           // erstes Zeichen
}

fn main() {
    assert_eq!(ersten_buchstaben("Hallo Welt"), Some('H'));
    assert_eq!(ersten_buchstaben(""), None);
}

Der ?-Operator ist eines der elegantesten Sprach-Features von Rust. In einer Funktion, die Option<T> zurückgibt, wandelt ? einen Option<U>-Ausdruck in U um — und macht bei None einen early return mit None.

Aus der match-basierten Variante mit fünf Zeilen pro Schritt wird eine einzige Zeile pro Schritt mit ?. Bei mehreren verketteten fallible Operationen reduziert das den Code-Umfang dramatisch. Vergleiche:

Ohne ?: let e = match s.split_whitespace().next() { Some(x) => x, None => return None };

Mit ?: let e = s.split_whitespace().next()?;

Der ?-Operator funktioniert sowohl auf Option als auch auf Result (mit etwas unterschiedlicher Semantik), und es gibt auch Konvertierung zwischen beiden über From. Im nächsten Artikel zu Result schauen wir das detailliert an.

Weitere wichtige Methoden

MethodeWas sie tut
is_some()true wenn Some
is_none()true wenn None
as_ref()Option<T>Option<&T>
as_mut()Option<T>Option<&mut T>
take()Wert herausnehmen, None zurücklassen
replace(x)Wert ersetzen, alten zurückgeben
or(other)self wenn Some, sonst other
or_else(f)self wenn Some, sonst f()
xor(other)genau eines von beiden, oder None
zip(other)Option<(A, B)> aus zwei Options
flatten()Option<Option<T>>Option<T>
contains(&x)true wenn Some(x) mit x == self.0
Rust as_ref + map
fn main() {
    let s = Some(String::from("Hi"));
    // Mit as_ref: nicht konsumieren
    let laenge: Option<usize> = s.as_ref().map(|x| x.len());
    // s ist hier noch nutzbar
    println!("{s:?} hat Länge {laenge:?}");
}

as_ref() ist die Konvertierungs-Methode, mit der du aus &Option<T> ein Option<&T> machst. Klingt unscheinbar, ist aber zentral: ohne as_ref würde s.map(|x| x.len()) den String s konsumieren — denn map nimmt den Wert per Move. Mit s.as_ref().map(|x| x.len()) arbeitest du nur auf einer Referenz, und der ursprüngliche Option<String> bleibt erhalten.

Dieses Pattern siehst du überall, wo Code mit Borrow-Semantik arbeitet — etwa bei &self-Methoden, die auf optionalen Feldern operieren wollen, ohne sie zu verbrauchen. Eine verwandte Methode ist as_mut() für mutable Referenzen.

take — Wert herausziehen

Rust take
fn main() {
    let mut o = Some(String::from("Hallo"));
    let extrahiert = o.take();          // o ist jetzt None
    assert_eq!(extrahiert, Some(String::from("Hallo")));
    assert_eq!(o, None);
}

take() ist eine elegante Lösung für ein häufiges Problem: du hast nur eine mutable Referenz auf eine Option und willst den inneren Wert herausnehmen. Direkter Move (o.unwrap()) ginge nicht, weil o eine Referenz ist. take() nimmt den Wert heraus und setzt das Original auf None.

Anwendungsfälle: In einer &mut self-Methode willst du ein Option-Feld konsumieren — self.feld.take() gibt dir den Inhalt, ohne self zu verbrauchen. Das ist die gleiche Mechanik wie std::mem::take für andere Typen, nur spezialisiert für Option mit None als Default.

Praxis: Option im echten Code

Optionale Config-Werte

Rust Konfiguration
pub struct AppConfig {
    pub host: String,
    pub port: u16,
    pub log_datei: Option<String>,           // optional
    pub max_workers: Option<u32>,            // optional
}

impl AppConfig {
    pub fn workers(&self) -> u32 {
        self.max_workers.unwrap_or(4)        // Default 4
    }

    pub fn loggt_in_datei(&self) -> bool {
        self.log_datei.is_some()
    }
}

Option<T> für optionale Felder. Default mit unwrap_or, Vorhandensein mit is_some.

Cache-Lookup

Rust Cache
use std::collections::HashMap;

pub struct Cache { eintraege: HashMap<String, Vec<u8>> }

impl Cache {
    pub fn holen(&self, key: &str) -> Option<&[u8]> {
        self.eintraege.get(key).map(|v| v.as_slice())
    }
}

fn main() {
    let mut c = Cache { eintraege: HashMap::new() };
    c.eintraege.insert("user:42".into(), vec![1, 2, 3]);

    // Idiomatischer Zugriff mit if let
    if let Some(daten) = c.holen("user:42") {
        println!("Cache-Hit: {} Bytes", daten.len());
    } else {
        println!("Cache-Miss");
    }
}

Cache-Lookups sind ein typisches Beispiel, bei dem Option natürlich passt: das Element könnte im Cache sein oder nicht. HashMap::get gibt Option<&V> zurück — bei einem Treffer eine Referenz auf den Wert, bei einem Miss None. Du musst explizit auf beide Fälle reagieren.

Das .map(|v| v.as_slice()) konvertiert die Option<&Vec<u8>> in Option<&[u8]> — mehr Flexibilität für den Aufrufer, weil Slice-Methoden auch auf Arrays und Sub-Bereichen funktionieren. Im main siehst du dann das idiomatische Verbrauchs-Muster: if let Some(daten) = ... greift nur den Hit-Fall, der else-Zweig den Miss.

Funktion mit „kann fehlen"-Semantik

Rust Suchen
pub fn finde_user_by_email(email: &str, users: &[(u64, String)]) -> Option<u64> {
    users.iter()
        .find(|(_, mail)| mail == email)
        .map(|(id, _)| *id)
}

fn main() {
    let users = vec![
        (1, "anna@example.com".to_string()),
        (2, "bert@example.com".to_string()),
    ];
    assert_eq!(finde_user_by_email("anna@example.com", &users), Some(1));
    assert_eq!(finde_user_by_email("unbekannt@example.com", &users), None);
}

Such-Funktionen geben naturgemäß Option zurück — entweder finden sie etwas oder nicht. Die find-Methode auf Iteratoren liefert Option<&Item>; mit .map(|x| ...) transformierst du das gefundene Element zu dem, was du eigentlich brauchst (hier die ID statt das ganze Tupel).

Diese find + map-Kombination ist überall in Rust-Code: „suche das passende Element, transformiere es zur gewünschten Repräsentation". Bei None (kein passendes Element gefunden) propagiert das automatisch durch — der Aufrufer bekommt None und muss den Nicht-Gefunden-Fall behandeln.

Chain von Operationen, jede kann fehlen

Rust Chain
pub fn ersten_satz(text: &str) -> Option<&str> {
    let trimmed = text.trim();
    if trimmed.is_empty() {
        return None;
    }
    trimmed.find('.').map(|i| &trimmed[..i])
}

fn main() {
    assert_eq!(ersten_satz("Hallo. Welt."), Some("Hallo"));
    assert_eq!(ersten_satz(""), None);
    assert_eq!(ersten_satz("Keine Punkt"), None);
}

Zwei Möglichkeiten zum frühen Ausstieg: is_emptyreturn None, dann find('.') mit map.

Iterator mit filter_map

Rust filter_map
fn main() {
    let raw_zahlen = ["42", "abc", "100", "x", "7"];
    let valide: Vec<i32> = raw_zahlen.iter()
        .filter_map(|s| s.parse().ok())
        .collect();
    assert_eq!(valide, vec![42, 100, 7]);
}

filter_map ist einer der elegantesten Iterator-Adapter überhaupt. Er kombiniert filter (Elemente verwerfen) und map (Elemente transformieren) in einer Operation: die Closure liefert Option<U>, und nur die Some(u)-Werte landen im Ergebnis.

Im Beispiel wird s.parse::<i32>() aufgerufen — das gibt Result<i32, ParseError> zurück. .ok() konvertiert das in Option<i32>: bei Erfolg Some(zahl), bei Fehler None. filter_map collect't dann nur die Some-Werte. Aus der gemischten Eingabe mit gültigen und ungültigen Strings werden nur die gültigen Zahlen extrahiert.

Diese Komposition aus filter_map und parse().ok() ist ein sehr typisches Idiom in Rust-Code für „nimm eine Liste von Strings, behalte nur die parsbaren als Zahlen". Drei Zeilen für etwas, das in vielen Sprachen mehrere Schritte mit explizitem Try/Catch-Boilerplate bräuchte.

Field-Update mit take

Rust State-Mutation
pub struct Buffer { inhalt: Option<Vec<u8>> }

impl Buffer {
    pub fn entnehmen(&mut self) -> Vec<u8> {
        self.inhalt.take().unwrap_or_default()
    }

    pub fn schreiben(&mut self, daten: Vec<u8>) {
        self.inhalt = Some(daten);
    }
}

fn main() {
    let mut b = Buffer { inhalt: Some(vec![1, 2, 3]) };
    let d = b.entnehmen();
    assert_eq!(d, vec![1, 2, 3]);
    assert!(b.inhalt.is_none());
}

take() extrahiert den Wert aus dem Option und setzt es auf None — ohne self zu verbrauchen.

Optionale Funktion-Parameter

Rust API-Design
pub fn baue_url(host: &str, port: Option<u16>) -> String {
    match port {
        Some(p) => format!("https://{host}:{p}"),
        None => format!("https://{host}"),
    }
}

fn main() {
    assert_eq!(baue_url("example.com", None), "https://example.com");
    assert_eq!(baue_url("example.com", Some(8443)), "https://example.com:8443");
}

Explizite Optionalität in der Signatur — kein „magisches null".

Frühe Validierung mit ? und ok_or

Rust Validierung
pub fn extrahiere_domain(email: &str) -> Result<&str, String> {
    let at_position = email.find('@').ok_or_else(|| String::from("kein @"))?;
    let domain = &email[at_position + 1..];
    if domain.is_empty() {
        return Err(String::from("Domain leer"));
    }
    Ok(domain)
}

find gibt Option, ok_or macht es zu Result, ? propagiert beim Err. Sehr kompakte Validierungs-Pipeline.

Default + Override

Rust Override-Pattern
pub fn timeout_ms(custom: Option<u64>) -> u64 {
    custom.unwrap_or(5_000)
}

pub fn timeout_ms_v2(custom: Option<u64>) -> u64 {
    custom.unwrap_or_else(|| {
        // teure Default-Berechnung (z. B. aus Config)
        aus_config()
    })
}

fn aus_config() -> u64 { 5_000 }

unwrap_or mit konstantem Default, unwrap_or_else mit lazy berechnetem Default.

Optional verschachtelt — flatten

Rust Nested Option
pub fn finde_user_email(users: &[(u64, Option<String>)], id: u64) -> Option<&String> {
    users.iter()
        .find(|(uid, _)| *uid == id)        // Option<&(u64, Option<String>)>
        .map(|(_, mail)| mail.as_ref())     // Option<Option<&String>>
        .flatten()                          // Option<&String>
}

fn main() {
    let users = vec![
        (1, Some("anna@example.com".to_string())),
        (2, None),
    ];
    assert!(finde_user_email(&users, 1).is_some());
    assert!(finde_user_email(&users, 2).is_none());
    assert!(finde_user_email(&users, 99).is_none());
}

flatten() macht aus Option<Option<T>> ein Option<T> — sehr nützlich bei verschachtelten Optionen.

FAQ

Wann unwrap?

Nur in Tests, Beispielen, oder wenn du beweisen kannst, dass None unmöglich ist. Im normalen Code: ?, unwrap_or, if let, match. expect("warum None hier unmöglich ist") ist besser als unwrap, weil der Panic mit Kontext kommt.

unwrap_or oder unwrap_or_else?

unwrap_or(default) wenn default billig ist (eine Konstante, ein Zero-Wert). unwrap_or_else(|| ...) wenn default eine teure Berechnung oder Allocation ist — dann wird sie nur bei None ausgewertet.

?-Operator auf Option vs. Result.

? funktioniert auf beiden — abhängig vom Rückgabe-Typ der umliegenden Funktion. Bei fn foo() -> Option<T> propagiert ? ein None. Bei fn foo() -> Result<T, E> propagiert ? ein Err. Mischformen brauchen ok_or zur Konvertierung.

Niche-Optimization macht Option<&T> kostenlos.

Option<&T> ist 8 Bytes auf 64-bit, identisch zu &T. Der Null-Pointer dient als None. Damit ist Option<&T> so effizient wie ein nullable Pointer in C — aber typsicher prüfbar.

map vs. and_then.

.map(f) wenn f ein normaler Wert zurückgibt: Option<T> → Option<U>. .and_then(f) wenn f selbst ein Option<U> zurückgibt — sonst hättest du Option<Option<U>>. Auch bekannt als „flatMap" in anderen Sprachen.

filter macht aus Some(v) None, wenn Predikat false.

Some(42).filter(|&n| n > 100) ergibt None. Nützlich für „nimm den Wert nur, wenn ...". Kombiniert mit map und and_then zu Functional-Style-Pipelines.

take ist für &mut self-Methoden Gold.

Wenn du in einer Methode mit &mut self-Receiver einen Option<Vec<...>>-Wert herausnehmen willst (ohne self zu verbrauchen), ist take() die Lösung. Standard-Pattern für „Field auf None setzen und alten Wert verarbeiten".

Vermeide if x.is_some() { x.unwrap() }.

Anti-Pattern. Stattdessen: if let Some(v) = x { ... }. Genau ein Pattern-Match statt zwei separate Checks. Clippy warnt darauf.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Enums & Pattern Matching

Zur Übersicht