GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing doc.rust-lang.org — std::option - Rust Expand descriptionOptional values. Type
§Options and pointers (“nullable” pointers)Rust’s pointer types must always point to a valid location; there are
no “null” references. Instead, Rust has optional pointers, like
the optional owned box, The following example uses §The question mark operator,
|
T | Transmuting between [0u8; size_of::<T>()] and Option::<T>::None sound? |
|---|---|
Box<U> (specifically, only Box<U, Global>) | when U: Sized |
&U | when U: Sized |
&mut U | when U: Sized |
fn, extern "C" fn1 | always |
num::NonZero* | always |
ptr::NonNull<U> | when U: Sized |
#[repr(transparent)] struct around one of the types in this list. | when it holds for the inner type |
Under some conditions the above types T are also null pointer optimized when wrapped in a Result.
This is called the “null pointer optimization” or NPO.
It is further guaranteed that, for the cases above, one can
mem::transmute from all valid values of T to Option<T> and
from Some::<T>(_) to T (but transmuting None::<T> to T
is undefined behavior).
In addition to working with pattern matching, Option provides a wide
variety of different methods.
The is_some and is_none methods return true if the Option
is Some or None, respectively.
The is_some_and and is_none_or methods apply the provided function
to the contents of the Option to produce a boolean value.
If this is None then a default result is returned instead without executing the function.
as_ref converts from &Option<T> to Option<&T>as_mut converts from &mut Option<T> to Option<&mut T>as_deref converts from &Option<T> to
Option<&T::Target>as_deref_mut converts from &mut Option<T> to
Option<&mut T::Target>as_pin_ref converts from Pin<&Option<T>> to
Option<Pin<&T>>as_pin_mut converts from Pin<&mut Option<T>> to
Option<Pin<&mut T>>as_slice returns a one-element slice of the contained value, if any.
If this is None, an empty slice is returned.as_mut_slice returns a mutable one-element slice of the contained value, if any.
If this is None, an empty slice is returned.These methods extract the contained value in an Option<T> when it
is the Some variant. If the Option is None:
expect panics with a provided custom messageunwrap panics with a generic messageunwrap_or returns the provided default valueunwrap_or_default returns the default value of the type T
(which must implement the Default trait)unwrap_or_else returns the result of evaluating the provided
functionunwrap_unchecked produces undefined behaviorThese methods transform Option to Result:
ok_or transforms Some(v) to Ok(v), and None to
Err(err) using the provided default err valueok_or_else transforms Some(v) to Ok(v), and None to
a value of Err using the provided functiontranspose transposes an Option of a Result into a
Result of an OptionThese methods transform the Some variant:
filter calls the provided predicate function on the contained
value t if the Option is Some(t), and returns Some(t)
if the function returns true; otherwise, returns Noneflatten removes one level of nesting from an Option<Option<T>>inspect method takes ownership of the Option and applies
the provided function to the contained value by reference if Somemap transforms Option<T> to Option<U> by applying the
provided function to the contained value of Some and leaving
None values unchangedThese methods transform Option<T> to a value of a possibly
different type U:
map_or applies the provided function to the contained value of
Some, or returns the provided default value if the Option is
Nonemap_or_else applies the provided function to the contained value
of Some, or returns the result of evaluating the provided
fallback function if the Option is NoneThese methods combine the Some variants of two Option values:
zip returns Some((s, o)) if self is Some(s) and the
provided Option value is Some(o); otherwise, returns Nonezip_with calls the provided function f and returns
Some(f(s, o)) if self is Some(s) and the provided
Option value is Some(o); otherwise, returns NoneThese methods treat the Option as a boolean value, where Some
acts like true and None acts like false. There are two
categories of these methods: ones that take an Option as input, and
ones that take a function as input (to be lazily evaluated).
The and, or, and xor methods take another Option as
input, and produce an Option as output. Only the and method can
produce an Option<U> value having a different inner type U than
Option<T>.
| method | self | input | output |
|---|---|---|---|
and | None | (ignored) | None |
and | Some(x) | None | None |
and | Some(x) | Some(y) | Some(y) |
or | None | None | None |
or | None | Some(y) | Some(y) |
or | Some(x) | (ignored) | Some(x) |
xor | None | None | None |
xor | None | Some(y) | Some(y) |
xor | Some(x) | None | Some(x) |
xor | Some(x) | Some(y) | None |
The and_then and or_else methods take a function as input, and
only evaluate the function when they need to produce a new value. Only
the and_then method can produce an Option<U> value having a
different inner type U than Option<T>.
| method | self | function input | function result | output |
|---|---|---|---|---|
and_then | None | (not provided) | (not evaluated) | None |
and_then | Some(x) | x | None | None |
and_then | Some(x) | x | Some(y) | Some(y) |
or_else | None | (not provided) | None | None |
or_else | None | (not provided) | Some(y) | Some(y) |
or_else | Some(x) | (not provided) | (not evaluated) | Some(x) |
This is an example of using methods like and_then and or in a
pipeline of method calls. Early stages of the pipeline pass failure
values (None) through unchanged, and continue processing on
success values (Some). Toward the end, or substitutes an error
message if it receives None.
let mut bt = BTreeMap::new();
bt.insert(20u8, "foo");
bt.insert(42u8, "bar");
let res = [0u8, 1, 11, 200, 22]
.into_iter()
.map(|x| {
// `checked_sub()` returns `None` on error
x.checked_sub(1)
// same with `checked_mul()`
.and_then(|x| x.checked_mul(2))
// `BTreeMap::get` returns `None` on error
.and_then(|x| bt.get(&x))
// Substitute an error message if we have `None` so far
.or(Some(&"error!"))
.copied()
// Won't panic because we unconditionally used `Some` above
.unwrap()
})
.collect::<Vec<_>>();
assert_eq!(res, ["error!", "error!", "foo", "error!", "bar"]);If T implements PartialOrd then Option<T> will derive its
PartialOrd implementation. With this order, None compares as
less than any Some, and two Some compare the same way as their
contained values would in T. If T also implements
Ord, then so does Option<T>.
OptionAn Option can be iterated over. This can be helpful if you need an
iterator that is conditionally empty. The iterator will either produce
a single value (when the Option is Some), or produce no values
(when the Option is None). For example, into_iter acts like
once(v) if the Option is Some(v), and like empty() if
the Option is None.
Iterators over Option<T> come in three types:
into_iter consumes the Option and produces the contained
valueiter produces an immutable reference of type &T to the
contained valueiter_mut produces a mutable reference of type &mut T to the
contained valueAn iterator over Option can be useful when chaining iterators, for
example, to conditionally insert items. (It’s not always necessary to
explicitly call an iterator constructor: many Iterator methods that
accept other iterators will also accept iterable types that implement
IntoIterator, which includes Option.)
let yep = Some(42);
let nope = None;
// chain() already calls into_iter(), so we don't have to do so
let nums: Vec<i32> = (0..4).chain(yep).chain(4..8).collect();
assert_eq!(nums, [0, 1, 2, 3, 42, 4, 5, 6, 7]);
let nums: Vec<i32> = (0..4).chain(nope).chain(4..8).collect();
assert_eq!(nums, [0, 1, 2, 3, 4, 5, 6, 7]);One reason to chain iterators in this way is that a function returning
impl Iterator must have all possible return values be of the same
concrete type. Chaining an iterated Option can help with that.
fn make_iter(do_insert: bool) -> impl Iterator<Item = i32> {
// Explicit returns to illustrate return types matching
match do_insert {
true => return (0..4).chain(Some(42)).chain(4..8),
false => return (0..4).chain(None).chain(4..8),
}
}
println!("{:?}", make_iter(true).collect::<Vec<_>>());
println!("{:?}", make_iter(false).collect::<Vec<_>>());If we try to do the same thing, but using once() and empty(),
we can’t return impl Iterator anymore because the concrete types of
the return values differ.
// This won't compile because all possible returns from the function
// must have the same concrete type.
fn make_iter(do_insert: bool) -> impl Iterator<Item = i32> {
// Explicit returns to illustrate return types not matching
match do_insert {
true => return (0..4).chain(once(42)).chain(4..8),
false => return (0..4).chain(empty()).chain(4..8),
}
}OptionOption implements the FromIterator trait,
which allows an iterator over Option values to be collected into an
Option of a collection of each contained value of the original
Option values, or None if any of the elements was None.
let v = [Some(2), Some(4), None, Some(8)];
let res: Option<Vec<_>> = v.into_iter().collect();
assert_eq!(res, None);
let v = [Some(2), Some(4), Some(8)];
let res: Option<Vec<_>> = v.into_iter().collect();
assert_eq!(res, Some(vec![2, 4, 8]));Option also implements the Product and
Sum traits, allowing an iterator over Option values
to provide the product and
sum methods.
let v = [None, Some(1), Some(2), Some(3)];
let res: Option<i32> = v.into_iter().sum();
assert_eq!(res, None);
let v = [Some(1), Some(2), Some(21)];
let res: Option<i32> = v.into_iter().product();
assert_eq!(res, Some(42));Option in-placeThese methods return a mutable reference to the contained value of an
Option<T>:
insert inserts a value, dropping any old contentsget_or_insert gets the current value, inserting a provided
default value if it is Noneget_or_insert_default gets the current value, inserting the
default value of type T (which must implement Default) if it is
Noneget_or_insert_with gets the current value, inserting a default
computed by the provided function if it is NoneThese methods transfer ownership of the contained value of an
Option:
take takes ownership of the contained value of an Option, if
any, replacing the Option with Nonereplace takes ownership of the contained value of an Option,
if any, replacing the Option with a Some containing the
provided valueBasic pattern matching on Option:
let msg = Some("howdy");
// Take a reference to the contained string
if let Some(m) = &msg {
println!("{}", *m);
}
// Remove the contained string, destroying the Option
let unwrapped_msg = msg.unwrap_or("default message");Initialize a result to None before a loop:
enum Kingdom { Plant(u32, &'static str), Animal(u32, &'static str) }
// A list of data to search through.
let all_the_big_things = [
Kingdom::Plant(250, "redwood"),
Kingdom::Plant(230, "noble fir"),
Kingdom::Plant(229, "sugar pine"),
Kingdom::Animal(25, "blue whale"),
Kingdom::Animal(19, "fin whale"),
Kingdom::Animal(15, "north pacific right whale"),
];
// We're going to search for the name of the biggest animal,
// but to start with we've just got `None`.
let mut name_of_biggest_animal = None;
let mut size_of_biggest_animal = 0;
for big_thing in &all_the_big_things {
match *big_thing {
Kingdom::Animal(size, name) if size > size_of_biggest_animal => {
// Now we've found the name of some big animal
size_of_biggest_animal = size;
name_of_biggest_animal = Some(name);
}
Kingdom::Animal(..) | Kingdom::Plant(..) => ()
}
}
match name_of_biggest_animal {
Some(name) => println!("the biggest animal is {name}"),
None => println!("there are no animals :("),
}this remains true for unsafe variants, any argument/return types, and any other ABI: [unsafe] extern "abi" fn (e.g., extern "system" fn) ↩
Some variant of an Option.Some variant of an Option.Some variant of an Option.Option::into_flat_iter. See its documentation for more.Option type. See the module level documentation for more.