gpt4 book ai didi

macros - 如何使用重复创建带有可选参数的 Rust 宏?

转载 作者:行者123 更新时间:2023-11-29 07:47:23 25 4
gpt4 key购买 nike

我目前正在研究 Rust 宏,但找不到任何关于重复的详细文档。我想创建带有可选参数的宏。这将是我的想法:

macro_rules! single_opt {
($mand_1, $mand_2, $($opt:expr)* ) =>{
match $opt {
Some(x) => println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, x);
None => single_opt!($mand_1, $mand_2, "Default");
}
}
}

fn main() {
single_opt!(4,4);
}

example似乎已经过时了,因为我无法编译它。 Rust 书非常简短地提到了这个主题。如何让这个示例起作用?

最佳答案

NOTE: Since this answer was written, Rust has gained the ability to express optional elements in a pattern (stabilized in Rust 1.32.0) using the syntax $(tokens)?.

Rust 书的第一版有一个 rather long chapter on macros ,但是关于重复的部分在示例上有点害羞...

有几种方法可以处理宏中的可选参数。如果你有一个只能出现一次的可选参数,那么你不应该使用重复:你应该在你的宏中定义多个模式,就像这样:

macro_rules! single_opt {
($mand_1:expr, $mand_2:expr) => {
single_opt!($mand_1, $mand_2, "Default")
};
($mand_1:expr, $mand_2:expr, $opt:expr) => {
println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, $opt)
};
}

fn main() {
single_opt!(4, 4);
}

如果你想允许任意数量的参数,那么你需要重复。您的原始宏不起作用,因为您将逗号放在重复之外,因此您必须将宏调用为 single_opt!(4,4,);。参见 How to allow optional trailing commas in macros?相关案例。

如果您有固定数量的参数后跟一个重复,您可以将逗号放在重复中作为第一个标记:

macro_rules! single_opt {
($mand_1:expr, $mand_2:expr $(, $opt:expr)*) => {
println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, $($opt),*)
};
}

但是,它在这种特定情况下不起作用:

error: 3 positional arguments in format string, but there are 2 arguments
--> src/main.rs:3:22
|
3 | println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, $($opt),*)
| ^^ ^^ ^^
...
8 | single_opt!(4, 4);
| ------------------
| |
| in this macro invocation
| in this macro invocation
| in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

所以我们必须回过头来定义两种模式:

macro_rules! single_opt {
($mand_1:expr, $mand_2:expr) => {
single_opt!($mand_1, $mand_2, "Default")
};
($mand_1:expr, $mand_2:expr, $($opt:expr),*) => {
{
println!("1. {} 2. {}", $mand_1, $mand_2);
$(
println!("opt. {}", $opt);
)*
}
};
}

fn main() {
single_opt!(4, 4, 1, 2);
}

重复的形式为 $( PATTERN ) SEPARATOR COUNT,其中 PATTERN 是您要重复的模式,SEPARATOR 是可选的分隔每个重复的标记(此处为 ,)和 COUNT* 表示“零次或多次出现”或 + 表示“一次或多次出现”。

然后,在宏扩展中,我们需要一个重复 block 才能访问$opt。语法完全相同,但请注意分隔符不必相同(此处,扩展中没有分隔符)。

关于macros - 如何使用重复创建带有可选参数的 Rust 宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34373169/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com