宏指示符
在Rust的宏编程中,宏可以接受多种类型的参数,称为"指示符"。这些指示符帮助宏识别不同类型的代码片段,并相应地处理它们。
这里列出全部指示符:
- block
- expr 用于表达式
- ident 用于变量名或函数名
- item
- literal 用于字面常量
- pat (模式 pattern)
- path
- stmt (语句 statement)
- tt (标记树 token tree)
- ty (类型 type)
- vis (可见性描述符)
ident
ident:标识符,用于变量名、函数名、类型名等。
rust
macro_rules! example {
($name:ident) => {
let $name = 42;
};
}
example!(x); // 展开为:let x = 42;
expr
expr:表达式,可以是任何合法的Rust表达式。
rust
macro_rules! example {
($e:expr) => {
println!("Result: {}", $e);
};
}
example!(1 + 2); // 展开为:println!("Result: {}", 1 + 2);
ty
ty:类型,用于指定类型名称。
rust
macro_rules! example {
($t:ty) => {
let _x: $t;
};
}
example!(i32); // 展开为:let _x: i32;
pat
pat:模式,用于模式匹配。
rust
macro_rules! example {
($p:pat) => {
match 42 {
$p => println!("Matched!"),
_ => println!("Not matched!"),
}
};
}
example!(x); // 展开为:match 42 { x => println!("Matched!"), _ => println!("Not matched!"), }
stmt
stmt:语句,用于单一语句。
rust
macro_rules! example {
($s:stmt) => {
$s
};
}
example!(let x = 42;); // 展开为:let x = 42;
block
block:代码块,用于多个语句组成的代码块。
rust
macro_rules! example {
($b:block) => {
$b
};
}
example!({
let x = 42;
println!("{}", x);
}); // 展开为:{ let x = 42; println!("{}", x); }
item
item:项,用于函数、结构体、模块等项。
rust
macro_rules! example {
($i:item) => {
$i
};
}
example!(fn foo() {}); // 展开为:fn foo() {}
meta
meta:元数据项,用于属性。
rust
macro_rules! example {
($m:meta) => {
#[$m]
fn foo() {}
};
}
example!(test); // 展开为:#[test] fn foo() {}
tt
tt:令牌树,表示一个或多个令牌。
rust
macro_rules! example {
($t:tt) => {
$t
};
}
example!(fn foo() {}); // 展开为:fn foo() {}
path
path :路径,用于路径(例如模块路径)。
rust macro_rules! example { ($p:path) => { let _: $p; }; } example!(std::io::Error); // 展开为:let _: std::io::Error;
literal
literal :字面量,用于常量值(字符串、数字等)。
rust macro_rules! example { ($l:literal) => { let x = $l; }; } example!("hello"); // 展开为:let x = "hello";
通过这些指示符,Rust的宏系统可以处理各种类型的输入,从而生成灵活且强大的代码。这些指示符使得宏在编写复杂代码时变得更加方便和可读。
代码示例
以下代码两个宏分别功能是创建函数和输出表达式及其结果
rust
macro_rules! create_function {
// 此宏接受一个 `ident` 指示符表示的参数,并创建一个名为 `$func_name` 的函数。
// `ident` 指示符用于变量名或函数名
($func_name: ident) => (
fn $func_name() {
// `stringify!` 宏把 `ident` 转换成字符串。
println!("You called {:?}()", stringify!($func_name))
}
)
}
// 借助上述宏来创建名为 `foo` 和 `bar` 的函数。
create_function!(foo);
create_function!(bar);
macro_rules! print_result {
// 此宏接受一个 `expr` 类型的表达式,并将它作为字符串,连同其结果一起
// 打印出来。
// `expr` 指示符表示表达式。
($expression: expr) => (
// `stringify!` 把表达式*原样*转换成一个字符串。
println!("{:?} = {:?}", stringify!($expression), $expression)
)
}
fn main() {
foo();
bar();
print_result!(1u32 + 1);
// 回想一下,代码块也是表达式!
print_result!({
let x = 1u32;
x * x + 2 * x - 1
});
}
``**