學習 Rust「2」減少代碼嵌套


學習 Rust「2」減少代碼嵌套


結論先行:減少代碼嵌套就是降低複雜度。

資源管理一向是編程中的重要任務。當一個函數要管理多個資源時,很容易出現代碼嵌套層級太深的問題,尤其是調用系統或第三方 API 時。

以 C 語言代碼為例,這裡簡化為兩個資源,請您自行腦補多個資源:

<code>int error_code = 0;
resource1 *p1 = new_resource1();
// UMU: with C++ SHOULD be `p1 != nullptr`
if (p1) {
resource2 *p2 = new_resource2();
if (p2) {
if (!deal_resources(p1, p2)) {
error_code = 3;
}
free_new_resource2(p2);
} else {
error_code = 2;
}
free_new_resource1(p1);
} else {}
error_code = 1;
}

return error_code;/<code>

上面代碼最深嵌套是三層,為了減少嵌套,可以把代碼改為平坦結構,降低到一層:

<code>resource1 *p1 = new_resource1(); 

if (!p1) {
free_new_resource1(p1);
return 1;
}

resource2 *p2 = new_resource2();
if (!p2) {
free_new_resource1(p1);
free_new_resource2(p2);
return 2;
}

if (!deal_resources(p1, p2)) {
free_new_resource1(p1);
free_new_resource2(p2);
return 3;
}

free_new_resource1(p1);
free_new_resource2(p2);/<code>

但這麼改在資源釋放時,更容易遺漏。也有人為使代碼層級平坦化,會使用 goto 到函數末尾統一釋放,或者更優雅點的 C++ 方式:用 try...throw...catch...finally 將所有資源包含起來管理。

Node.js 的異步回調函數也存在嵌套層級過深的問題,可以用 Promise 來平坦化,參考:

<code>setTimeout(() => {
console.log('step1')
setTimeout(() => {
console.log('step2')
setTimeout(function() {
console.log('step3')
console.log('done!')
}, 1000)
}, 1000)
}, 1000)

// flatten
let timer = (text) => {
let promise = new Promise((resolve, reject) => {

setTimeout(() => {
console.log(text)
resolve()
}, 1000)
})

return promise
}

timer("step1")
.then(() => {
return timer("step2")
})
.then(() => {
return timer("step3")
})
.then(() => {
console.log("done!")
})/<code>

C++ 建議使用 RAII 思想來管理資源,獲得資源後立刻放到管理對象裡。如果有些資源使用得不頻繁,想偷懶不去封裝,則可以使用 scope_exit。go 語言更是用內置關鍵字 defer 來提供 scope_exit 機制。

Rust 用 scopeguard 提供 scope_exit 機制,defer! 宏和 go 的 defer 功能類似。

另外,Rust 還有 ? 操作符,也有減少嵌套的作用。比如這個任務:打開文件,如果失敗就返回錯誤。go 是這樣寫的:

<code>package main

import (
\t"os"
)

func main() {
\tfile, error := os.Open("file.txt")
\tif error != nil {
\t\tpanic(error)
\t}

\tdefer file.Close()
}/<code>

同樣功能,Rust 代碼少一層:

<code>use std::fs::File;

fn main() -> std::io::Result {
let _f = File::open("file.txt")?;
Ok(())
}/<code>


分享到:


相關文章: