声明性宏 - 括号中的表达式后面可以跟任意匹配器。为什么?
Declarative macros - bracketed expressions can be followed by arbitrary matchers. Why?
我正在试验声明性宏,我考虑过使用它们重新创建 F# 序列表达式。
第一次尝试触发了编译错误:
macro_rules! genexp {
(for $item:ident in $range:expr -> $expr:expr) => {
$range.map(|$item| $expr)
}
}
`$range:expr` is followed by `->`, which is not allowed for `expr` fragments
allowed there are: `=>`, `,` or `;`rustc
但是,以下代码可以编译并正常工作:
macro_rules! genexp {
(for $item:ident in [$range:expr] -> $expr:expr) => {
$range.map(|$item| $expr)
}
}
fn main() {
let foo = genexp!(for x in [0..20] -> x * x);
println!("{:?}", foo.collect::<Vec<_>>())
}
//OUTPUT: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361]
我的问题是,为什么? Rust 参考中的 Macros By Example 部分指出:
expr
and stmt
may only be followed by one of: =>
, ,
, or ;
.
我没有看到关于各种括号或其他分隔符的特殊处理的信息。
$range:expr ->
Rust 语言将来可以扩展,其中 ->
成为表达式的有效部分。这个想法是宏明确地 future-compatible 随着对 Rust 的更新,所以这是不允许保守的。
[$range:expr] ->
Rust 语言永远不会扩展涉及不平衡的特性 brackets/parents/braces [](){}
。因此,当 Rust 解析器看到 [
时,它可以立即扫描匹配的 ]
。因此,这个宏的哪一部分是表达式,以及表达式停止和 ] ->
出现的位置是明确的,即使面对未来的语言扩展。
我正在试验声明性宏,我考虑过使用它们重新创建 F# 序列表达式。 第一次尝试触发了编译错误:
macro_rules! genexp {
(for $item:ident in $range:expr -> $expr:expr) => {
$range.map(|$item| $expr)
}
}
`$range:expr` is followed by `->`, which is not allowed for `expr` fragments
allowed there are: `=>`, `,` or `;`rustc
但是,以下代码可以编译并正常工作:
macro_rules! genexp {
(for $item:ident in [$range:expr] -> $expr:expr) => {
$range.map(|$item| $expr)
}
}
fn main() {
let foo = genexp!(for x in [0..20] -> x * x);
println!("{:?}", foo.collect::<Vec<_>>())
}
//OUTPUT: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361]
我的问题是,为什么? Rust 参考中的 Macros By Example 部分指出:
expr
andstmt
may only be followed by one of:=>
,,
, or;
.
我没有看到关于各种括号或其他分隔符的特殊处理的信息。
$range:expr ->
Rust 语言将来可以扩展,其中 ->
成为表达式的有效部分。这个想法是宏明确地 future-compatible 随着对 Rust 的更新,所以这是不允许保守的。
[$range:expr] ->
Rust 语言永远不会扩展涉及不平衡的特性 brackets/parents/braces [](){}
。因此,当 Rust 解析器看到 [
时,它可以立即扫描匹配的 ]
。因此,这个宏的哪一部分是表达式,以及表达式停止和 ] ->
出现的位置是明确的,即使面对未来的语言扩展。