2014-09-16 13 views
8

Ví dụ:Tại sao không phải là một biểu thức tính toán SPAN các khối finally

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

Bạn không thể làm các do! trong cuối cùng bạn nhận được thông báo từ các trình biên dịch "bạn chỉ có thể sử dụng làm trong một biểu thức tính toán "nhưng nó vẫn ở trong đó đúng.

Tôi biết cách tôi có thể giải quyết vấn đề này nhưng tôi muốn hiểu tại sao trình biên dịch hạn chế kịch bản này.

Ok sau khi một số fiddeling Tôi nghĩ rằng nó khử đường như thế này: (Tôi rất hạnh phúc, chúng tôi có thể viết cexprs)

từ:

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

tới:

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

tôi nhận được rằng phần thứ hai của TryFinally không hỗ trợ một số cexpr.

+0

Làm bài tập, để hiểu hành vi này, hãy cố gắng loại bỏ quy trình làm việc. Bạn sẽ thấy cách chuỗi kết quả của các cuộc gọi hàm làm cho điều này là không thể. – Daniel

+0

@ Vesa.A.J.K: Tôi không cho rằng đó là một khái niệm không thể, chỉ là cách thức quy trình công việc hiện nay được desugared ngăn cản nó. – Daniel

+0

@ Vesa.AJK Tôi đoán nó không phải là quá nhiều giám sát như là một quyết định đơn giản hóa việc thực hiện để có được sản phẩm ra cửa nhanh hơn – phoog

Trả lời

7

Như đã thảo luận trong câu hỏi, các biểu thức try-finally với biểu thức tính toán cho mệnh đề finally đơn giản là không được hỗ trợ (trong F # 3.1). Tuy nhiên, thật dễ dàng để thực hiện một hàm có hành vi cơ bản như vậy. Dưới đây là ví dụ về triển khai:

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

Tuyệt vời bạn thậm chí cung cấp một giải pháp :) – albertjan

+4

Điều này sẽ không gọi kết thúc khi cơ thể được làm trống trước do hủy bỏ. –

Các vấn đề liên quan