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

时间:2014-09-16 13:31:29

标签: f# f#-async

例如:

let test () = 
    async {
        try 
           do! someting ()
        finally
           do! sometingElse ()
    }

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

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

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

从:

async {
    try 
       do! someting ()
       do! sometingElse ()
    finally
       printfn "finally"
}

为:

async.TryFinally(
    async.Bind(
        someting(), (fun () -> 
            async.Bind(sometingElse (), (fun () -> 
                async.Zero())))), (fun () -> printfn "finally")) |> ignore

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

1 个答案:

答案 0 :(得分: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
}