2014-09-16 9 views
8

Zum Beispiel:Warum nicht ein Berechnungsausdruck Pannenblock des schließlich

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

Sie können die do! in der schließlich nicht tun Sie die Nachricht von dem Compiler erhalten „Sie tun können in einem Berechnung Ausdruck "aber es ist immer noch drin richtig.

Ich weiß, wie ich das lösen kann, aber ich würde gerne verstehen, warum der Compiler dieses Szenario einschränkt.

Ok, nachdem einige fiddeling Ich denke, es so entzuckert ist: (Ich bin sehr glücklich, dass wir cexprs schreiben)

aus:

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

zu:

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

ich dass der zweite Teil der TryFinally keine cexpr unterstützt.

+0

Um dieses Verhalten zu verstehen, sollten Sie versuchen, den Arbeitsablauf zu entziffern. Sie werden sehen, wie die daraus resultierende Reihe von Funktionsaufrufen dies unmöglich macht. – Daniel

+0

@ Vesa.A.J.K: Ich behaupte nicht, dass es ein unmögliches Konzept ist, nur dass die Art und Weise, wie Arbeitsabläufe derzeit entschärft werden, es verhindert. – Daniel

+0

@ Vesa.AJK Ich denke, es ist nicht so sehr ein Versehen als eine Entscheidung, die Implementierung zu vereinfachen, um das Produkt schneller aus der Tür zu bekommen – phoog

Antwort

7

Wie bereits in der Frage diskutiert, werden try-finally Ausdrücke mit einem Berechnungsausdruck für die finally-Klausel einfach nicht unterstützt (in F # 3.1). Es ist jedoch einfach, eine Funktion zu implementieren, die im Wesentlichen ein solches Verhalten aufweist. Hier eine Beispielimplementierung:

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 
} 
+0

Awesome Sie sogar eine Lösung zur Verfügung gestellt :) – albertjan

+4

Dies wird nicht finalisieren, wenn der Körper wegen Kündigung vorweggenommen ist. –

Verwandte Themen