Suche…


Einführung

Der Option<T> -Typ ist Rusts Entsprechung von nullfähigen Typen ohne alle damit verbundenen Probleme. Die Mehrheit der C-ähnlichen Sprachen lässt zu, dass jede Variable null wenn keine Daten vorhanden sind. Der Option Typ ist jedoch von funktionalen Sprachen inspiriert, die 'Optionals' bevorzugen (z. B. die Haskell- Maybe " Maybe ). Wenn Sie Option verwenden, können Sie die Idee ausdrücken, dass Daten möglicherweise vorhanden sind oder nicht (da Rust keine nullfähigen Typen hat).

Optionswert und Musterübereinstimmung erstellen

// The Option type can either contain Some value or None.
fn find(value: i32, slice: &[i32]) -> Option<usize> {
    for (index, &element) in slice.iter().enumerate() {
        if element == value {
            // Return a value (wrapped in Some).
            return Some(index);
        }
    }
    // Return no value.
    None
}

fn main() {
    let array = [1, 2, 3, 4, 5];
    // Pattern match against the Option value.
    if let Some(index) = find(2, &array) {
        // Here, there is a value.
        println!("The element 2 is at index {}.", index);
    }

    // Check if the result is None (no value).
    if let None = find(12, &array) {
        // Here, there is no value.
        println!("The element 12 is not in the array.");
    }

    // You can also use `is_some` and `is_none` helpers
    if find(12, &array).is_none() {
        println!("The element 12 is not in the array.");
    }
}

Option zerstören

fn main() {
    let maybe_cake = Some("Chocolate cake");
    let not_cake = None;

    // The unwrap method retrieves the value from the Option
    // and panics if the value is None
    println!("{}", maybe_cake.unwrap());

    // The expect method works much like the unwrap method,
    // but panics with a custom, user provided message.
    println!("{}", not_cake.expect("The cake is a lie."));

    // The unwrap_or method can be used to provide a default value in case
    // the value contained within the option is None. This example would
    // print "Cheesecake".
    println!("{}", not_cake.unwrap_or("Cheesecake"));

    // The unwrap_or_else method works like the unwrap_or method,
    // but allows us to provide a function which will return the
    // fallback value. This example would print "Pumpkin Cake".
    println!("{}", not_cake.unwrap_or_else(|| { "Pumpkin Cake" }));

    // A match statement can be used to safely handle the possibility of none.
    match maybe_cake {
        Some(cake) => println!("{} was consumed.", cake),
        None       => println!("There was no cake.")
    }

    // The if let statement can also be used to destructure an Option.
    if let Some(cake) = maybe_cake {
        println!("{} was consumed.", cake);
    }
}

Auspacken eines Verweises auf eine Option, die den Inhalt besitzt

Ein Verweis auf eine Option &Option<T> kann nicht entpackt werden, wenn der Typ T nicht kopierbar ist. Die Lösung besteht darin, die Option mit as_ref() in &Option<&T> as_ref() .

Rost verbietet die Übertragung des Eigentums an Gegenständen, während die Gegenstände ausgeliehen werden. Wenn die Option selbst ausgeliehen wird ( &Option<T> ), wird ihr Inhalt auch indirekt geliehen.

#[derive(Debug)]
struct Foo;
 
fn main() {
    let wrapped = Some(Foo);
    let wrapped_ref = &wrapped;
    
    println!("{:?}", wrapped_ref.unwrap()); // Error!
}

Der geliehene Inhalt kann nicht verschoben werden [--explain E0507]

Es ist jedoch möglich, einen Verweis auf den Inhalt von Option<T> zu erstellen. Die as_ref() Methode der Option gibt eine Option für &T , die ohne Eigentumsübertragung ausgepackt werden kann:

println!("{:?}", wrapped_ref.as_ref().unwrap());

Option mit Karte und and_then verwenden

Die map Operation ist ein nützliches Werkzeug, wenn Sie mit Arrays und Vektoren arbeiten, sie kann jedoch auch dazu verwendet werden, Option funktional zu behandeln.

fn main() {

    // We start with an Option value (Option<i32> in this case).
    let some_number = Some(9);

    // Let's do some consecutive calculations with our number.
    // The crucial point here is that we don't have to unwrap
    // the content of our Option type - instead, we're just
    // transforming its content. The result of the whole operation
    // will still be an Option<i32>. If the initial value of
    // 'some_number' was 'None' instead of 9, then the result
    //  would also be 'None'.
    let another_number = some_number
        .map(|n| n - 1) // => Some(8)
        .map(|n| n * n) // => Some(64)
        .and_then(|n| divide(n, 4)); // => Some(16)

    // In the last line above, we're doing a division using a helper
    // function (definition: see bottom).
    // 'and_then' is very similar to 'map', but allows us to pass a
    // function which returns an Option type itself. To ensure that we
    // don't end up with Option<Option<i32>>, 'and_then' flattens the
    // result (in other languages, 'and_then' is also known as 'flatmap').

    println!("{}", to_message(another_number));
    // => "16 is definitely a number!"

    // For the sake of completeness, let's check the result when
    // dividing by zero.
    let final_number = another_number
        .and_then(|n| divide(n, 0)); // => None

    println!("{}", to_message(final_number));
    // => "None!"
}

// Just a helper function for integer division. In case
// the divisor is zero, we'll get 'None' as result.
fn divide(number: i32, divisor: i32) -> Option<i32> {
    if divisor != 0  { Some(number/divisor) } else { None }
}

// Creates a message that tells us whether our
// Option<i32> contains a number or not. There are other
// ways to achieve the same result, but let's just use
// map again!
fn to_message(number: Option<i32>) -> String {
    number
        .map(|n| format!("{} is definitely a number!", n)) // => Some("...")
        .unwrap_or("None!".to_string()) // => "..."
}


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow