教程
巨集允許我們抽象多次重複的語法模式。例如:
/// 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 嘗試 )