具有相同分隔符的并排宏重复
Side by side macro repetition with same separator
实际上不可能创建这样的宏还是我做错了:
sample!("hello", "there") =>
println!("{:?}", "hello");
println!("{:?}", "there");
sample!("hello", "there", a "second type", a "another second type") =>
println!("{:?}", "hello");
println!("{:?}", "there");
println!("second {:?}", "second type");
println!("second {:?}", "another second type");
我试过的是这个 (playground link):
macro_rules! sample {
(
$( $first:literal ),*
$( a $second:literal ),*
) => {
$(
println!("{:?}", $first);
)*
$(
println!("second {:?}", $second);
)*
};
}
失败:
error: no rules expected the token `a`
--> main.rs:18:20
|
1 | macro_rules! sample {
| ------------------- when calling this macro
...
18 | sample!("hello", a "testing");
| ^ no rules expected this token in macro call
error: aborting due to previous error
您几乎做对了 - 结尾的逗号使编译器出错。 Removing the comma works just fine. 如果您想知道为什么,那是因为 macro_rules
调用非常挑剔。当它读取尾随逗号时,它会查看下一个标记,即 a
,但由于这不是文字,因此它没有做更明智的事情,即检查下一个模式,而是放弃了。
Rust 宏对其分隔符非常严格。
macro_rules! sample {
(
$( $first:literal, )*
$( a $second:literal ),*
) => {
$(println!("{:?}", $first);)*
$(println!("second {:?}", $second);)*
};
}
fn main() {
sample!("hello", a "testing");
}
这个示例有效,你能发现变化吗?我把第一个 $( ... )
外面的逗号移到了里面。区别是:
$( $a:literal ),*
仅接受 "a", "b", "c"
(不允许尾随逗号)
$( $a:literal, )*
仅接受 "a", "b", "c",
(需要尾随逗号)
在您的宏中,中间逗号作为第一次或第二次重复的一部分不匹配。错误基本上是说它期望另一个 $first
而不是 $second
因为这就是重复所说的。
您可以通过引入可选的逗号来修复它:
macro_rules! sample {
(
$( $first:literal ),*
$(,)? // <----------------
$( a $second:literal ),*
) => {
$(println!("{:?}", $first);)*
$(println!("second {:?}", $second);)*
};
}
哪个更宽松,但会允许像这样奇怪的事情,这可能会也可能不会,这取决于你想要什么。
sample!("hello", "there",);
sample!(, a "testing");
sample!("hello" a "testing");
不幸的是,如果不像这样使用不同的手臂,我不知道完美的解决方案:
macro_rules! sample {
($( $first:literal ),*) => { };
($( $first:literal, )* $( a $second:literal ),+) => { };
($( a $second:literal ),*) => { };
}
fn main() {
sample!("hello", "there");
sample!("hello", "there", a "testing");
sample!(a "second type", a "another second type");
// sample!("hello", "there",);
// sample!(, a "testing");
// sample!("hello" a "testing");
}
另请参阅:
- How do I create a Rust macro with optional parameters using repetitions?
实际上不可能创建这样的宏还是我做错了:
sample!("hello", "there") =>
println!("{:?}", "hello");
println!("{:?}", "there");
sample!("hello", "there", a "second type", a "another second type") =>
println!("{:?}", "hello");
println!("{:?}", "there");
println!("second {:?}", "second type");
println!("second {:?}", "another second type");
我试过的是这个 (playground link):
macro_rules! sample {
(
$( $first:literal ),*
$( a $second:literal ),*
) => {
$(
println!("{:?}", $first);
)*
$(
println!("second {:?}", $second);
)*
};
}
失败:
error: no rules expected the token `a`
--> main.rs:18:20
|
1 | macro_rules! sample {
| ------------------- when calling this macro
...
18 | sample!("hello", a "testing");
| ^ no rules expected this token in macro call
error: aborting due to previous error
您几乎做对了 - 结尾的逗号使编译器出错。 Removing the comma works just fine. 如果您想知道为什么,那是因为 macro_rules
调用非常挑剔。当它读取尾随逗号时,它会查看下一个标记,即 a
,但由于这不是文字,因此它没有做更明智的事情,即检查下一个模式,而是放弃了。
Rust 宏对其分隔符非常严格。
macro_rules! sample {
(
$( $first:literal, )*
$( a $second:literal ),*
) => {
$(println!("{:?}", $first);)*
$(println!("second {:?}", $second);)*
};
}
fn main() {
sample!("hello", a "testing");
}
这个示例有效,你能发现变化吗?我把第一个 $( ... )
外面的逗号移到了里面。区别是:
$( $a:literal ),*
仅接受"a", "b", "c"
(不允许尾随逗号)$( $a:literal, )*
仅接受"a", "b", "c",
(需要尾随逗号)
在您的宏中,中间逗号作为第一次或第二次重复的一部分不匹配。错误基本上是说它期望另一个 $first
而不是 $second
因为这就是重复所说的。
您可以通过引入可选的逗号来修复它:
macro_rules! sample {
(
$( $first:literal ),*
$(,)? // <----------------
$( a $second:literal ),*
) => {
$(println!("{:?}", $first);)*
$(println!("second {:?}", $second);)*
};
}
哪个更宽松,但会允许像这样奇怪的事情,这可能会也可能不会,这取决于你想要什么。
sample!("hello", "there",);
sample!(, a "testing");
sample!("hello" a "testing");
不幸的是,如果不像这样使用不同的手臂,我不知道完美的解决方案:
macro_rules! sample {
($( $first:literal ),*) => { };
($( $first:literal, )* $( a $second:literal ),+) => { };
($( a $second:literal ),*) => { };
}
fn main() {
sample!("hello", "there");
sample!("hello", "there", a "testing");
sample!(a "second type", a "another second type");
// sample!("hello", "there",);
// sample!(, a "testing");
// sample!("hello" a "testing");
}
另请参阅:
- How do I create a Rust macro with optional parameters using repetitions?