Control Flow Option Options

Match

Ah, the good ol’ match statement. Generally very powerful, one can use it for measly Option matching:

fn <>(: <>) where : std::fmt:: {
    match  {
        () => !("Got some value: {value:?}"),
         => !("Got no value"),
    }
}

Or with more complex match goodness, like match guards and bindings:

fn (: <>, : ) {
    match  {
        () if  >  => !("I am really sorry"),
        () if  ==  => !("What are the odds?"),
        ( @ 1.0..10.0) => !("So close!! Only {value} left..."),
        (_) => !("Some ways to go..."),
         => !("Debt free!"),
    }
}

If Let

Equivalent to checking for a Some while simultaneously unwrapping the containing value:

fn (: <>) {
  if let ( @ ..100.0) =  {
      !("Debt below three digits!! Only {value} remaining."),
  } else {
      !("Unable to perform analysis..."),
  }
}

This allows you to reduce one level of nesting, as compared to the match version:

fn (: <>) {
    match  {
        ( @ ..100.0) => {
            !("Debt below three digits!! Only {value} remaining."),
        },
         => {
            !("Unable to perform analysis..."),
        }
    }
}

Note that if you do not need the containing value, use .is_some() with an if expression:

fn (: <>) {
    if .() {
        !("You have debt."),
    } else {
        !("You do not have debt."),
    }
}

Let Else

The irrefutable version of if let. Use this to unwrap a value, changing control flow if the Option is None:

fn (: <>, : ) {
    let () =  else {
        !("No debt.");
        return;
    }

    let  =  / ;
    !("You owe {debt}.");
    !("You pay {annual_deposit} a year towards your debt.");
    !("You will repay your debt after {} years.", );
}

This allows you to reduce one level of nesting after the unwrapping, as compared to the if let version:

fn (: <>, : ) {
    if let () =  {
        let  =  / ;
        !("You owe {debt}.");
        !("You pay {annual_deposit} a year towards your debt.");
        !("You will repay your debt after {} years.", );
    } else {
        !("No debt.");
    }
}

Note that if you want to panic!() or unreachable!() on None, use .expect() or .unwrap() instead.

fn (: <>, : ) {
    let  = .("Everyone has debt.");

    let  =  / ;
    !("You owe {debt}.");
    !("You pay {annual_deposit} a year towards your debt.");
    !("You will repay your debt after {} years.", );
}
src
fn calculate_years_to_repay(debt: Option<f64>, annual_deposit: f64)
core::option::Option
Some(T)

Some value of type T.

let value: T
std::macros
macro_rules! eprintln

Prints to the standard error, with a newline.

Equivalent to the [println] macro, except that output goes to [io::stderr] instead of [io::stdout]. See [println] for example usage.

Use eprintln! only for error and progress messages. Use println! instead for the primary output of your program.

See the formatting documentation in std::fmt for details of the macro argument syntax.

Panics

Panics if writing to io::stderr fails.

Writing to non-blocking stderr can cause an error, which will lead this macro to panic.

Examples

eprintln!("Error: Could not complete task");
core::fmt
// Dyn Compatible: Yes
pub trait Debug

? formatting.

Debug should format the output in a programmer-facing, debugging context.

Generally speaking, you should just derive a Debug implementation.

When used with the alternate format specifier #?, the output is pretty-printed.

For more information on formatters, see the module-level documentation.

This trait can be used with #[derive] if all fields implement Debug. When derived for structs, it will use the name of the struct, then {, then a comma-separated list of each field’s name and Debug value, then }. For enums, it will use the name of the variant and, if applicable, (, then the Debug values of the fields, then ).

Stability

Derived Debug formats are not stable, and so may change with future Rust versions. Additionally, Debug implementations of types provided by the standard library (std, core, alloc, etc.) are not stable, and may also change with future Rust versions.

Examples

Deriving an implementation:

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

let origin = Point { x: 0, y: 0 };

assert_eq!(
    format!("The origin is: {origin:?}"),
    "The origin is: Point { x: 0, y: 0 }",
);

Manually implementing:

use std::fmt;

struct Point {
    x: i32,
    y: i32,
}

impl fmt::Debug for Point {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Point")
         .field("x", &self.x)
         .field("y", &self.y)
         .finish()
    }
}

let origin = Point { x: 0, y: 0 };

assert_eq!(
    format!("The origin is: {origin:?}"),
    "The origin is: Point { x: 0, y: 0 }",
);

There are a number of helper methods on the Formatter struct to help you with manual implementations, such as [debug_struct].

Types that do not wish to use the standard suite of debug representations provided by the Formatter trait (debug_struct, debug_tuple, debug_list, debug_set, debug_map) can do something totally custom by manually writing an arbitrary representation to the Formatter.

impl fmt::Debug for Point {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Point [{} {}]", self.x, self.y)
    }
}

Debug implementations using either derive or the debug builder API on Formatter support pretty-printing using the alternate flag: {:#?}.

Pretty-printing with #?:

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

let origin = Point { x: 0, y: 0 };

let expected = "The origin is: Point {
    x: 0,
    y: 0,
}";
assert_eq!(format!("The origin is: {origin:#?}"), expected);
f64

A 64-bit floating-point type (specifically, the “binary64” type defined in IEEE 754-2008).

This type is very similar to prim@f32, but has increased precision by using twice as many bits. Please see the documentation for f32 or Wikipedia on double-precision values for more information.

See also the std::f64::consts module.

debt: Option<f64>
T: Debug
core::option::Option
None

No value.

net_worth: f64
annual_deposit: f64
let repay_years: f64
option: Option<T>
src
fn analyze_debt(debt: Option<f64>)
let value: f64
src
fn debug_option<T>(option: Option<T>)
where
    T: std::fmt::Debug,
core::option
pub enum Option<T> {
    None,
    Some( /* … */ ),
}

The Option type. See the module level documentation for more.

let amount: f64
src
fn check_debt(debt: Option<f64>, net_worth: f64)
core::option::Option
impl<T> Option<T>
pub const fn expect(self, msg: &str) -> T

Returns the contained Some value, consuming the self value.

Panics

Panics if the value is a None with a custom panic message provided by msg.

Examples

let x = Some("value");
assert_eq!(x.expect("fruits are healthy"), "value");
let x: Option<&str> = None;
x.expect("fruits are healthy"); // panics with `fruits are healthy`

Recommended Message Style

We recommend that expect messages are used to describe the reason you expect the Option should be Some.

let item = slice.get(0)
    .expect("slice should not be empty");

Hint: If you’re having trouble remembering how to phrase expect error messages remember to focus on the word “should” as in “env variable should be set by blah” or “the given binary should be available and executable by the current user”.

For more detail on expect message styles and the reasoning behind our recommendation please refer to the section on “Common Message Styles” in the std::error module docs.

core::option::Option
impl<T> Option<T>
pub const fn is_some(&self) -> bool

Returns true if the option is a Some value.

Examples

let x: Option<u32> = Some(2);
assert_eq!(x.is_some(), true);

let x: Option<u32> = None;
assert_eq!(x.is_some(), false);