| Crates.io | orderless |
| lib.rs | orderless |
| version | 0.1.5 |
| created_at | 2023-05-11 11:19:23.910777+00 |
| updated_at | 2023-05-21 22:28:03.020642+00 |
| description | Orderless/named functions in Rust. `add!(b = 2); // 4`. |
| homepage | |
| repository | https://github.com/Kyza/orderless |
| max_upload_size | |
| id | 861997 |
| size | 25,016 |
orderless generates macros for you that allow you to use orderless/named functions in Rust.
#[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
impl).const and static variables.a = a to a.impl_orderless for make_orderless in impl blocks.Documentation is provided on docs.rs.
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.
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.
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!`.
macro_rules! two {
( $($arg_name:ident $(= $arg_value:expr)?),*$(,)? ) => {
::orderless::call_orderless!(
func = two,
defs(a = false, b = false),
args($($arg_name $(= $arg_value)?),*),
)
};
() => {
::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_orderlessmake_orderless is an attribute macro which simplifies the process even more by grabbing info already available in the function's definition.
#[make_orderless(defs(a = false, b = false))]
fn two<T>(a: T, b: T) -> (T, T) {
(a, b)
}
// Generates the same thing as `create_orderless!`...
impl_orderlessThe main problem with make_orderless is that since it generates a macro_rules! right there, it can't be used inside of impl blocks.
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.
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)!