教程
宏允许我们抽象多次重复的语法模式。例如:
/// Computes `a + b * c`. If any of the operation overflows, returns `None`.
fn checked_fma(a: u64, b: u64, c: u64) -> Option<u64> {
let product = match b.checked_mul(c) {
Some(p) => p,
None => return None,
};
let sum = match a.checked_add(product) {
Some(s) => s,
None => return None,
};
Some(sum)
}
我们注意到两个 match
语句非常相似:它们都具有相同的模式
match expression {
Some(x) => x,
None => return None,
}
想象一下,我们将上面的模式表示为 try_opt!(expression)
,然后我们可以将函数重写为 3 行:
fn checked_fma(a: u64, b: u64, c: u64) -> Option<u64> {
let product = try_opt!(b.checked_mul(c));
let sum = try_opt!(a.checked_add(product));
Some(sum)
}
try_opt!
无法编写函数,因为函数不支持早期返回。但我们可以用宏来做 - 只要我们有这些无法使用函数表示的语法模式,我们就可以尝试使用宏。
我们使用 macro_rules!
语法定义一个宏:
macro_rules! try_opt {
// ^ note: no `!` after the macro name
($e:expr) => {
// ^~~~~~~ The macro accepts an "expression" argument, which we call `$e`.
// All macro parameters must be named like `$xxxxx`, to distinguish from
// normal tokens.
match $e {
// ^~ The input is used here.
Some(x) => x,
None => return None,
}
}
}
而已! 我们创建了第一个宏。
(在 Rust Playground 尝试 )