#macro-rules #macro #proc-macro

macro_rules_rec

macro_rules 的语法扩展,以启用自递归调用

1 个不稳定版本

0.1.0 2024 年 4 月 20 日

Rust 模式 中排名 #1595

MIT 许可协议

19KB
375 行(不含注释)

macro_rules_rec crate 允许在 Rust 语言中,在 macro_rules! 中进行自我递归调用。

在 Rust 中,宏(尤其是使用 macro_rules! 定义的宏)在使用时会就地展开宏的主体。这意味着在展开过程中产生的所有中间状态都必须遵循 Rust 的语法。

特别是,当宏在其主体中递归调用自身时,此调用写入的位置必须在 Rust 语法支持宏调用的语法元素内。通常,许多宏旨在展开为表达式、语句、类型或声明项,这很少引起问题。然而,在以下特殊情况中,宏调用的位置不对应于 Rust 中的任何语法元素,这传统上阻止了宏的递归调用

  • 在泛型的 where 子句中使用单个宏同时生成类型和约束的对。
  • 在结构体声明中使用单个宏同时生成字段名和类型的对。

macro_rules_rec 扩展了 Rust 的 macro_rules! 的声明性宏编写,并允许无语法限制的递归宏调用。此外,由 macro_rules_rec 生成的宏是纯 macro_rules! 并不依赖于外部 crate(包括 macro_rules_rec)。这在创建库时非常有用,因为库的用户在使用用其生成的宏时不需要引用 macro_rules_rec

示例

您可以通过 $self! 语句执行自我递归调用。

# use macro_rules_rec::recursive;
#[recursive]
macro_rules! m {
    ($($id:ident)*) => {
        $(
            $self!(@ $id);
        )*
    };
    (@ $id:ident) => {
        #[allow(unused)]
        let $id = 123;
    };
}
m!(a b c);

依赖

~1.5MB
~37K SLoC