F# 为什么';t计算表达式跨越最后一个块
例如:F# 为什么';t计算表达式跨越最后一个块,f#,f#-async,F#,F# Async,例如: let test () = async { try do! someting () finally do! sometingElse () } 你不能做do在最后,您从编译器获得消息“您只能在计算表达式中使用do!”,但它仍然在那里 我知道如何解决这个问题,但我想了解编译器为什么会限制这个场景 好吧,在做了一些小动作之后,我想它是这样的:(我很高兴我们可以编写CEXPR) 发件人: 致: 我
let test () =
async {
try
do! someting ()
finally
do! sometingElse ()
}
你不能做do代码>在最后,您从编译器获得消息“您只能在计算表达式中使用do!”,但它仍然在那里
我知道如何解决这个问题,但我想了解编译器为什么会限制这个场景
好吧,在做了一些小动作之后,我想它是这样的:(我很高兴我们可以编写CEXPR)
发件人:
致:
我知道TryFinally
的第二部分不支持cexpr
正如问题中已经讨论过的那样,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
}
let tryFinally(body:Async=Async{
let!result=Async.Catch正文
完成!完成
使用返回匹配结果
|选择1OF2值->值
|选择2OF2 exn->提升exn
}
作为练习,要理解这种行为,请尝试对工作流进行去语法化。您将看到生成的一系列函数调用是如何使这不可能的。@Vesa.A.J.K:我不是说这是一个不可能的概念,只是工作流当前的去语法化方式阻止了它。@Vesa.A.J.K我想这与其说是一个疏忽,不如说是一个决策继续简化实现以便更快地推出产品谢谢各位,很明显这不是由于编译器的限制或其他原因,它只是没有实现。你们中有人想正式回答这个问题并获得代表吗?:@Vesa.a.J.K也许你们应该实现它——它是开源的,毕竟:)太棒了,你甚至提供了一个解决方案:)当主体由于取消而被抢占时,这不会调用finalize。
async.TryFinally(
async.Bind(
someting(), (fun () ->
async.Bind(sometingElse (), (fun () ->
async.Zero())))), (fun () -> printfn "finally")) |> ignore
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
}