Crate guard [] [src]

This crate exports a macro which implements most of RFC 1303 (a "let-else" or "guard" expression as you can find in Swift).

The syntax proposed in the RFC was if !let PAT = EXPR { BODY } or let PAT = EXPR else { BODY } (where BODY must diverge). Due to implementation details, this macro has the rather awkward syntax guard!({ BODY } unless EXPR => PAT). Alternative syntaxes may be added in the future.

Example usage:

#[macro_use] extern crate guard;
use std::env;
 
fn main() {
    // read configuration from a certain environment variable
    // do nothing if the variable is missing
    guard!({ return } unless env::var("FOO") => Ok(foo));
 
    println!("FOO = {}", foo);
}

Limitations

  1. Expressions in the pattern are not supported. This is a limitation of the current Rust macro system -- I'd like to say "parse an identifier in this position, but if that fails try parsing an expression" but this is is impossible; I can only test for specific identifiers. It's easy to get around this restriction: use a pattern guard (as in match) instead.
  2. Empty, un-namespaced enum variants and structs cause the expansion to fail, because the macro thinks they are identifiers. It's possible to get around this as well, though an open PR is aiming to take away the easiest workaround: a. For empty enum variants, use Empty(..) until #29383 lands, after that include the enum name as in Enum::Empty. b. For unit-like structs, use Empty(..) until #29383 lands, after that namespace it as in namespace::Empty, or use Empty{} (requires #![feature(braced_empty_structs)]).
  3. PAT cannot be irrefutable. This is the same behavior as if let and match, and it's useless to write a guard with an irrefutable pattern anyway (you can just use let), so this shouldn't be an issue. This is slightly more annoying than it could be due to limitation #1. Nonetheless, if #14252 is ever fixed, irrefutable patterns could be allowed by inserting a no-op pattern guard into the expansion.

Macros

guard!

Match a pattern to an expression, binding identifiers in the calling scope. Diverge if the match fails.