#proc-macro #macro #named #named-arguments #generator #default-value #generate

orderless

Rust 中的无序/命名函数。 add!(b = 2); // 4

6 个版本

0.1.5 2023 年 5 月 21 日
0.1.4 2023 年 5 月 21 日

1562Rust 模式

Download history 10/week @ 2024-03-12 7/week @ 2024-03-26 23/week @ 2024-04-02 1/week @ 2024-05-21

每月 66 次下载

MIT 许可证

23KB
452

orderless!

orderless 为您生成宏,允许您在 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 的函数)。
  • 默认参数值。
    • 标识符。
    • 表达式。
    • conststatic 变量。
    • 可选地不提供默认值。
  • 快捷方式将相同名称和值简化为仅名称。 a = aa
  • 属性宏 impl_orderlessmake_orderlessimpl 块中。

文档

文档提供在 docs.rs

它如何工作?

调用 call_orderless!

call_orderless! 是执行所有重工作的过程宏。它接受一些信息,如函数的名称、参数的顺序和默认值。

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

正如您所看到的,单独使用它并没有什么意义。但它非常适合其他宏将其信息传递给它。

创建 call_orderless!

create_orderless! 是另一个辅助宏。它通过生成一个具有大部分内置信息的 macro_rules! 宏来简化编写 call_orderless! 的过程。

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);

现在您有一个类似于函数的宏,可以非常简单地进行使用。

make_orderless

make_orderless 是一个属性宏,它通过获取函数定义中已存在的信息来进一步简化过程。

#[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_orderless

make_orderless的主要问题在于它直接生成一个macro_rules!宏,因此不能在impl块中使用。

struct Args {}

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

幸运的是,impl_orderless宏使这成为可能。

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)
	}
}

它是通过删除所有make_orderless属性并将它们转换为create_orderless!来实现的,这些转换在impl块之外。

所有这些链式调用都形成了宏的嵌套。一个将宏转换为另一个宏的宏,该宏创建一个宏,该宏调用另一个宏。但最终,这些都属于编译时,对运行时性能没有影响。two!()简单地编译为two(false, false)

依赖项

~1.6–2.2MB
~42K SLoC