https://github.com/kyza/orderless
Generates macros for you that allow you to use orderless/named functions in Rust.
https://github.com/kyza/orderless
Last synced: 12 months ago
JSON representation
Generates macros for you that allow you to use orderless/named functions in Rust.
- Host: GitHub
- URL: https://github.com/kyza/orderless
- Owner: Kyza
- License: mit
- Created: 2023-05-11T11:15:40.000Z (about 3 years ago)
- Default Branch: trunk
- Last Pushed: 2023-06-02T13:32:34.000Z (about 3 years ago)
- Last Synced: 2025-06-13T16:41:42.760Z (about 1 year ago)
- Language: Rust
- Homepage: https://crates.io/crates/orderless
- Size: 33.2 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 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
- [x] Attribute macro.
- [x] Procedural macro.
- [x] Paths to functions (functions from crates and `impl`).
- [x] Default argument values.
- [x] Identifiers.
- [x] Expressions.
- [x] `const` and `static` variables.
- [x] Optionally don't provide a default value.
- [x] Shortcut identical name and value to just the name. `a = a` to `a`.
- [x] Attribute macro `impl_orderless` for `make_orderless` in `impl` blocks.
## Docs
Documentation is provided on [docs.rs](https://docs.rs/orderless).
## 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!`.
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_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)`!