在嵌套的 Rust 宏中动态创建参数
Dynamically creating parameters in nested rust macros
我研究 Rust 的宏系统已经有一段时间了,最近对将两个宏嵌套在一起产生了兴趣,就像这样:
macro_rules! foo {
() => {
macro_rules! bar {
() => {}
}
}
}
关于这个例子,我想在 bar!
中动态创建传递给 foo!
的参数名称,以获得这样的结果:
foo!(bar, baz);
// The above call creates a macro, bar!, with the following definition:
macro_rules! bar {
( $bar:literal, $baz:literal ) => {
println!("{}", stringify!( $bar, $baz ));
}
}
为了更好地了解我正在尝试做的事情,这是我对它如何工作的初步思考过程(这应该完全解析为上面显示的定义):
macro_rules! foo {
( $( $attr:ident ), * ) => {
macro_rules! bar {
// the designator $$attr:literal consists of two parts - $attr,
// which should be replaced with the arguments passed into foo!,
// and $__:literal, which creates a literal designator for each of
// the arguments from foo! for bar!
( $( $$attr:literal ), * ) => {
// $( $$attr ), * follows the same logic as above
println!("{}", stringify!( $( $$attr ), * ));
}
}
}
}
这看起来确实很奇怪,果然,它没有用,给出了一个错误提示meta-variable expressions and this issue, both of which looked unrelated (full error can be seen on the playground)。
有谁知道是否可以使用这样的变量动态创建宏,如果可以,该怎么做?
是的,但是...
您不能插入 $
符号,因为它是为元变量保留的。
你有两种选择来解决这个问题。
在稳定版中,您需要将 $
传递给宏。然后它可以使用元变量引用它。
macro_rules! foo {
( $dollar:tt $( $attr:ident ), * ) => {
macro_rules! bar {
( $( $dollar $attr:literal ), * ) => {
println!("{}", stringify!( $( $dollar $attr ), * ));
}
}
}
}
foo!($ bar, baz);
在夜间,您可以转义美元符号:这是编译器提到的 macro_metavar_expr
功能的一部分。您可以使用 $$
:
#![feature(macro_metavar_expr)]
macro_rules! foo {
( $( $attr:ident ), * ) => {
macro_rules! bar {
( $( $$ $attr:literal ), * ) => {
println!("{}", stringify!( $( $$ $attr ), * ));
}
}
}
}
foo!(bar, baz);
我研究 Rust 的宏系统已经有一段时间了,最近对将两个宏嵌套在一起产生了兴趣,就像这样:
macro_rules! foo {
() => {
macro_rules! bar {
() => {}
}
}
}
关于这个例子,我想在 bar!
中动态创建传递给 foo!
的参数名称,以获得这样的结果:
foo!(bar, baz);
// The above call creates a macro, bar!, with the following definition:
macro_rules! bar {
( $bar:literal, $baz:literal ) => {
println!("{}", stringify!( $bar, $baz ));
}
}
为了更好地了解我正在尝试做的事情,这是我对它如何工作的初步思考过程(这应该完全解析为上面显示的定义):
macro_rules! foo {
( $( $attr:ident ), * ) => {
macro_rules! bar {
// the designator $$attr:literal consists of two parts - $attr,
// which should be replaced with the arguments passed into foo!,
// and $__:literal, which creates a literal designator for each of
// the arguments from foo! for bar!
( $( $$attr:literal ), * ) => {
// $( $$attr ), * follows the same logic as above
println!("{}", stringify!( $( $$attr ), * ));
}
}
}
}
这看起来确实很奇怪,果然,它没有用,给出了一个错误提示meta-variable expressions and this issue, both of which looked unrelated (full error can be seen on the playground)。
有谁知道是否可以使用这样的变量动态创建宏,如果可以,该怎么做?
是的,但是...
您不能插入 $
符号,因为它是为元变量保留的。
你有两种选择来解决这个问题。
在稳定版中,您需要将 $
传递给宏。然后它可以使用元变量引用它。
macro_rules! foo {
( $dollar:tt $( $attr:ident ), * ) => {
macro_rules! bar {
( $( $dollar $attr:literal ), * ) => {
println!("{}", stringify!( $( $dollar $attr ), * ));
}
}
}
}
foo!($ bar, baz);
在夜间,您可以转义美元符号:这是编译器提到的 macro_metavar_expr
功能的一部分。您可以使用 $$
:
#![feature(macro_metavar_expr)]
macro_rules! foo {
( $( $attr:ident ), * ) => {
macro_rules! bar {
( $( $$ $attr:literal ), * ) => {
println!("{}", stringify!( $( $$ $attr ), * ));
}
}
}
}
foo!(bar, baz);