orderless!

orderless generates macros for you that allow you to use orderless/named functions in Rust.

```rs

[make_orderless(defs(a = 2))]

fn add(a: usize, b: usize) -> usize { a + b }

// Compiles to add(2, 2) for no runtime performance hit! add!(b = 2); // 4 ```

Features

Docs

Documentation is provided on docs.rs.

How does it work?

call_orderless!

call_orderless! is the proc macro that does all the heavy lifting. It takes a bunch of info such as the function's name, the order of the arguments, and the default values.

rs call_orderless! { func = two, order(a, b), defs(a = false, b = false), args(a = true, b = false), }

As you can see, using it on its own is pretty pointless. But it's perfect for other macros to pass info they have to it.

create_orderless!

create_orderless! is another helper macro. It simplifies the process of writing call_orderless! by generating a macro_rules! macro which has most of the info built in.

```rs create_orderless! { func = two, order(a, b), defs(a = false, b = false) }

// Generates... // Note order(...) disappears because it's integrated into defs(...) by create_orderless!. macrorules! two { ( $($argname:ident $(= $argvalue:expr)?),*$(,)? ) => { ::orderless::callorderless!( func = two, defs(a = false, b = false), args($($argname $(= $argvalue)?),*), ) }; () => { ::orderless::call_orderless!( func = two, defs(a = false, b = false), args(), ) }; }

// Called like... two!(b = true); ```

Now you have a function-like macro which can be used very simply.

make_orderless

make_orderless is an attribute macro which simplifies the process even more by grabbing info already available in the function's definition.

```rs

[make_orderless(defs(a = false, b = false))]

fn two(a: T, b: T) -> (T, T) { (a, b) }

// Generates the same thing as create_orderless!... ```

impl_orderless

The main problem with make_orderless is that since it generates a macro_rules! right there, it can't be used inside of impl blocks.

```rs struct Args {}

impl Args { #[make_orderless(defs(a = false, b = false))] // ERROR!! pub fn two(a: bool, b: bool) -> (bool, bool) { (a, b) } } ```

Fortunately, the impl_orderless macro makes this possible.

```rs struct Args {}

[impl_orderless]

impl Args { #[make_orderless(defs(a = false, b = false))] // SUCCESS!! pub fn two(a: bool, b: bool) -> (bool, bool) { (a, b) } } ```

It does this by removing all the make_orderless attributes and converting them into create_orderless! outside of the impl block.

With all this chaining it's macro-ception. A macro that converts a macro to another macro, which creates a macro, which calls a macro. But in the end this is all compile-time and doesn't impact runtime performance at all. two!() simply compiles to two(false, false)!