Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# exception handling constructs

Why doesn't F# naturally support a try/with/finally block?

Doesn't it make sense to try something, deal with whatever exception it throws, at least to log the exception, and then be sure that some code executes after all that?

Sure, we can do

try
    try
        ...
    with ex -> ...
finally
    ...

But that seems too artificial, it clearly demonstrates that "F# is against try/with/finally". Why is that?

like image 212
Bruno Reis Avatar asked Jan 16 '10 19:01

Bruno Reis


3 Answers

As somebody already mentioned, you would usually use try-with-finally to make sure that you properly release all resources in case of an exception. I think in most of the cases you can do this more easily using the use keyword:

let input = 
  try
    use stream = new FileStream("C:\temp\test.txt");
    use rdr = new StreamReader(stream);
    Some(rdr.ReadToEnd())
  with :? IOException as e -> 
    logError(e)
    None

I think this is mostly the reason why you don't need try-with-finally as often as you would in other languages. But of course, there are some situations where you may need it (but you could of course avoid that by creating instance of IDisposable using object expressions (which is syntactically very easy). But I think this is so rare that the F# team doesn't really need to worry about this.

like image 83
Tomas Petricek Avatar answered Oct 12 '22 07:10

Tomas Petricek


Orthogonality? You can simply nest a try-with inside a try-finally, as you show. (This is what happens at the IL level anyway, I think.)

That said, try-with-finally is something that we may consider in a future version of the language.

Personally I have only run into wanting it a couple times, but when you do need it, it is a little bothersome to have to do the extra nesting/indent. In general I find that I rarely write exception handling code, and it's usually just one or the other (e.g. a finally to restore an invariant or other transactional semantics, or a 'catch' near the top of an app to log an exception or show the user diagnostics).

But I don't think there's a lot to 'read in to' regarding the language design here.

like image 34
Brian Avatar answered Oct 12 '22 07:10

Brian


Without going into great detail because the great details are in

Expert .NET 2.0 IL Assembler by Serge Lidin

See: Ch. 14, Managed Exception Handling

"The finally and fault handlers cannot peacefully coexist with other handlers, so if a guarded block has a finally or fault handler, it cannot have anything else. To combine a finally or fault handler with other handlers, you need to nest the guarded and handler bocks within other guarded blocks, ..., so that each finally or fault handler has its own personal guarded block."

pg. 300

A try/catch uses a fault handler and a try/finally uses a finally handler.

See: ILGenerator.BeginFaultBlock Method

If you emit a fault handler in an exception block that also contains a catch handler or a finally handler, the resulting code is unverifiable.

So, all of the .net languages could be consider to be using syntactic surgar and since F# is so new, they just haven't implemented it yet. No harm no fould.

like image 23
Guy Coder Avatar answered Oct 12 '22 06:10

Guy Coder