Rust 元組匹配的一個妙用
Rust 元組匹配的一個妙用
原文:https://nathanael-morris-bennett.medium.com/rust-tuple-pattern-matching-trick-c0f6bcdb4460
PS:原文的示例代碼中有幾處語法錯誤,本文對其進行了修正,並且示例代碼也有所不同。
如下代碼模仿一個人一天的行爲。
fn work()->Result<(), String> {
// TODO
Ok(())
}
fn eat()-> Result<(), String> {
// TODO
Ok(())
}
fn fuck()-> Result<(), String> {
// TODO
Ok(())
}
fn sleep() {
// TODO
}
fn handle_err(e: String){
// TODO
}
fn handle_ok() {
// TODO
}
要求在所有事情都順利完成(返回 ()
)之後才能睡覺,否則直接返回,不接着做後面的事情。那麼普通情況怎麼寫呢?
fn main() {
if let Ok(_) = work() {
if let Ok(_) = eat() {
if let Ok(_) = fuck() {
handle_ok()
} else if let Err(e3) = fuck() {
handle_err(e3)
}
}else if let Err(e2) =eat() {
handle_err(e2)
}
}else if let Err(e) = work() {
handle_err(e)
}
}
這就是最直白的,一個一個的去判斷,但是,如果你使用 match 則可以寫出下面這種代碼
fn main() {
match (work(), eat(), fuck()) {
(Ok(_), Ok(_), Ok(_)) => sleep(),
(Err(e), _, _) | (_, Err(e), _) | (_, _, Err(e)) => handle_err(e),
}
}
怎麼樣?是不是簡單了很多?也清楚了很多,如果三個函數返回的 Err 是不同類型的,也只需要把第二個條件拆分爲多個 Option,但是代碼可讀性依舊會很強。甚至於如果你不管什麼返回什麼 Err 類型的處理邏輯都是一樣的,那麼你甚至可以直接用 -
代替第二個匹配條件。
但是實際上,這個方式是三個方法都執行完了最終確定要不要 sleep,如果使用內聯閉包則可以寫成這樣
fn main() {
match (|| Ok((work()?, eat()?, fuck()?)))() {
Ok((_, _, _)) => sleep(),
Err(e) => handle_err(e),
}
}
這就可以保證當前一個函數沒有成功執行的時候根本不會執行下一個。原作者在文中還講了一個 and_than 的方法,因爲那樣寫連第一種都不如,所以本文不做介紹