为什么计算表达式不跨越finally块

alb*_*jan 8 f# f#-async

例如:

let test () = 
    async {
        try 
           do! someting ()
        finally
           do! sometingElse ()
    }
Run Code Online (Sandbox Code Playgroud)

你不能做到do!最后你从编译器得到消息"你只能在计算表达式中使用do!"但它仍然在那里.

我知道如何解决这个问题,但我想了解编译器限制这种情况的原因.

好了一些fiddeling后,我觉得它像这样沮丧:(我很高兴我们可以写cexprs)

从:

async {
    try 
       do! someting ()
       do! sometingElse ()
    finally
       printfn "finally"
}
Run Code Online (Sandbox Code Playgroud)

至:

async.TryFinally(
    async.Bind(
        someting(), (fun () -> 
            async.Bind(sometingElse (), (fun () -> 
                async.Zero())))), (fun () -> printfn "finally")) |> ignore
Run Code Online (Sandbox Code Playgroud)

我知道第二部分TryFinally不支持a cexpr.

小智 7

正如问题中已经讨论过的那样,根本不支持try-finally带有finally子句计算表达式的表达式(在F#3.1中).但是,很容易实现具有这种行为的功能.这是一个示例实现:

let tryFinally (body: Async<'x>) (finalize: Async<unit>) : Async<'x> = async {
    let! result = Async.Catch body
    do! finalize
    return match result with
           | Choice1Of2 value -> value
           | Choice2Of2 exn -> raise exn
}
Run Code Online (Sandbox Code Playgroud)

  • 当机构因取消而被抢占时,这不会调用finalize. (4认同)