Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 为什么';t计算表达式跨越最后一个块_F#_F# Async - Fatal编程技术网

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
}