我正在撰寫一個異步方法,它應該異步查詢一個埠,直到找到一個,或者在 5 分鐘后超時;
member this.GetPort(): Async<Port> = this._GetPort(DateTime.Now)
member this._GetPort(startTime: DateTime): Async<Port> = async {
match this._TryGetOpenPort() with
| Some(port) -> port
| None -> do
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
else
do! Async.Sleep(100)
let! result = this._GetPort(startTime)
result}
member this._TryGetOpenPort(): Option<Port> =
// etc.
但是,我在_GetPort; 中遇到了一些奇怪的型別不一致問題。該函式說我正在回傳一種型別Async<unit>而不是Async<Port>。
uj5u.com熱心網友回復:
這有點不直觀,但讓你的代碼作業的方法是這樣的:
member private this.GetPort(startTime: DateTime) =
async {
match this.TryGetOpenPort() with
| Some port ->
return port
| None ->
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
do! Async.Sleep(100)
let! result = this.GetPort(startTime)
return result
}
member private this.TryGetOpenPort() = failwith "yeet" // TODO
我冒昧地清理了一些東西并將成員設為私有,因為這似乎是您在這里主要追求的目標,并使用更詳細的內部方法來獲取埠。
您的代碼未編譯的原因是因為您return在計算中的內容不一致:
- 如果
Some(port)您缺少return關鍵字 - 需要將值提升回Async<port> - 您
if引發例外的運算式有一個else分支,但您沒有return同時來自這兩個分支。在這種情況下,由于您顯然不希望回傳任何內容而只是引發例外,因此您可以省略else并使其成為命令式程式流,就像在非異步代碼中一樣。
您可能希望考慮的另一件事是拋出例外是否是您想要的,或者只是回傳 aResult<T,Err>或一個選項是正確的呼叫。例外本身并不壞,但如果有一種很好的方法可以將意義賦予包裝回傳值的型別,那么很多 F# 編程通常會導致避免使用它們。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/318795.html
