#macro #chain

no-std if_chain

Macro for writing nested if let expressions

7 releases (3 stable)

Uses old Rust 2015

1.0.2 Aug 21, 2021
1.0.1 Sep 29, 2020
1.0.0 May 22, 2019
0.1.3 Jul 20, 2018
0.1.1 Dec 29, 2016

#60 in Rust patterns

Download history 147383/week @ 2023-11-02 152597/week @ 2023-11-09 163569/week @ 2023-11-16 131062/week @ 2023-11-23 153655/week @ 2023-11-30 145453/week @ 2023-12-07 130275/week @ 2023-12-14 78434/week @ 2023-12-21 92412/week @ 2023-12-28 143917/week @ 2024-01-04 152928/week @ 2024-01-11 176117/week @ 2024-01-18 153559/week @ 2024-01-25 158283/week @ 2024-02-01 160648/week @ 2024-02-08 114942/week @ 2024-02-15

620,402 downloads per month
Used in 732 crates (61 directly)

MIT/Apache

10KB
139 lines

if_chain

Build Status Cargo

This crate provides a single macro called if_chain!.

if_chain! lets you write long chains of nested if and if let statements without the associated rightward drift. It also supports multiple patterns (e.g. if let Foo(a) | Bar(a) = b) in places where Rust would normally not allow them.

For more information on this crate, see the documentation and associated blog post.


lib.rs:

This crate provides a single macro called if_chain!.

if_chain! lets you write long chains of nested if and if let statements without the associated rightward drift. It also supports multiple patterns (e.g. if let Foo(a) | Bar(a) = b) in places where Rust would normally not allow them.

See the associated blog post for the background behind this crate.

Note about recursion limits

If you run into "recursion limit reached" errors while using this macro, try adding

#![recursion_limit = "1000"]

to the top of your crate.

Examples

Quick start

if_chain! {
    if let Some(y) = x;
    if y.len() == 2;
    if let Some(z) = y;
    then {
        do_stuff_with(z);
    }
}

becomes

if let Some(y) = x {
    if y.len() == 2 {
        if let Some(z) = y {
            do_stuff_with(z);
        }
    }
}

Fallback values with else

if_chain! {
    if let Some(y) = x;
    if let Some(z) = y;
    then {
        do_stuff_with(z)
    } else {
        do_something_else()
    }
}

becomes

if let Some(y) = x {
    if let Some(z) = y {
        do_stuff_with(z)
    } else {
        do_something_else()
    }
} else {
    do_something_else()
}

Intermediate variables with let

if_chain! {
    if let Some(y) = x;
    let z = y.some().complicated().expression();
    if z == 42;
    then {
       do_stuff_with(y);
    }
}

becomes

if let Some(y) = x {
    let z = y.some().complicated().expression();
    if z == 42 {
        do_stuff_with(y);
    }
}

Type ascription

let mut x = some_generic_computation();
if_chain! {
    if x > 7;
    let y: u32 = another_generic_computation();
    then { x += y }
    else { x += 1 }
}

becomes

let mut x = some_generic_computation();
if x > 7 {
    let y: u32 = another_generic_computation();
    x += y
} else {
    x += 1
}

Multiple patterns

if_chain! {
    if let Foo(y) | Bar(y) | Baz(y) = x;
    let Bubbles(z) | Buttercup(z) | Blossom(z) = y;
    then { do_stuff_with(z) }
}

becomes

match x {
    Foo(y) | Bar(y) | Baz(y) => match y {
        Bubbles(z) | Buttercup(z) | Blossom(z) => do_stuff_with(z)
    },
    _ => {}
}

Note that if you use a plain let, then if_chain! assumes that the pattern is irrefutable (always matches) and doesn't add a fallback branch.

No runtime deps