[][src]Crate shoogah

shoogah is a crate with all sorts of syntactic sugar for Rust. Many of the items are inspired from the goodness of other languages, especially Groovy. Some operations require an expanded notion of what is true and what is false. In these cases, we make use of the AsBool trait. Any type that implements AsBool, will work with shoogah.

Easy HashMap literals with the hml! macro

Define a std::collections::HashMap via a simple literal.

    let my_map = hml! [
        "a": 1,
        "b": 2,
        "c": 1 + 2,
    ];

In this example, my_map is of type std::collections::HashMap<&str, i32>. To create an empty map:

    let mut my_map = hml![:];
    my_map.insert("a", 1);

Note that in the case of an empty map declaration like this one, only after you insert an entry will the map have its type inferred. So if you try to use the empty map before inserting any entries, you'll get a compiler error. If your use case requires the empty map, add type annotations to the left hand side like this:

    use std::collections::HashMap;
    let mut my_map: HashMap<&str, u8> = hml![:];

Map keys can be identifiers (variable names) or lietrals like 1 or "Hello". Map values can be any type of expression.

Compact conditional expressions with the cxp! macro

    let x = "";
    let username = cxp!{ (x) ? (x) : ("Bytor") }; // username assigned "Bytor"

Given how complex expressions can be, the parentheses are required.

Elvis says: "Don't Repeat Yourself"; elv! macro

    let x = "Cygnus";
    let username = elv!{ (x) ?: ("Bytor") }; // username remains "Cygnus"

Elvis says: "Don't Repeat Yourself... again"; ela! macro

If the assigned-to variable is the condition being tested, the Elvis assignment macro (ela!) is for you.

    let mut username = "";
    ela!{ username ?= "Bytor" }; // username is now "Bytor"

Simple increment and decrement with the suf! macro

    let mut x = 1;
    assert_eq!(2, suf!{ x++ });
    assert_eq!(1, suf!{ x-- });

Collect common field values from an Iterator with the spr! macro

    #[derive(Clone)]
    struct Address<'a> {
        country: &'a str,
    }

    #[derive(Clone)]
    struct Customer<'c> {
        name: &'c str,
        address: Address<'c>,
    }

   let customers = vec![
       Customer{ name: "Carlos", address: Address{ country: "Spain" }},
       Customer{ name: "Johnathan", address: Address{ country: "United Kingdom" }},
       Customer{ name: "Enzo", address: Address{ country: "Italy" }},
   ];
   let countries: Vec<_> = spr! { (customers)*.address*.country };
   assert_eq!(vec!["Spain", "United Kingdom", "Italy"], countries);

Note that the operation requires collections that implement Iterator and items that implement Clone, given they are moved out of the original. Also note that parentheses are required for the first expression, allowing for chaining and literals as the initial collection.

String interpolation with sin!

    // Normal string literal, no inner quotes (") allowed.
    let mut msg = sin!{ "1 + 1 = ${ 1 + 1 }" };
    assert_eq!("1 + 1 = 2", msg);
    // Raw string literal, inner quotes (") are allowed.
    msg = sin!{ r#"Hello, ${ "World!" }"# };
    assert_eq!("Hello, World!", msg);

Expressions within the ${} can be almost anything except something containing a closing brace }.

Boolean coercion with boo!

    let x = 1; let y = 0;
    assert_eq!(true, boo!{ x });
    assert_eq!(false, boo!{ y });

Here we make use of the rules for what's true or false from the AsBool trait.

It's all still Rust under the hood

All these macros expand into normal Rust code, so the usual syntax and type requirements will apply to variable names, literals, and expressions that you use.

Macros

boo

Boolean coercion

cxp

Express an if/else in a shorthand manner. This is sometimes called the ternary operator in other languages.

ela

When the assigned-to variable is the condition being tested, Elvis assign (ela!) can help even more.

elv

When the main result of an if/else is the same as the tested condition, Elvis (elv!) is here to help.

hml

Define a std::collections::HashMap via a simple literal.

sin

String interpolation.

spr

Collect common field values from an Iterator.

suf

Incrementing or decrementing by 1.

Traits

AsBool

AsBool defines a type's behavior in a boolean context. Basically, it converts the implementing type to bool.