views:

169

answers:

2

During normal program's execution an exception may occur.

In case I'm aware of it and just want to ignore it — how do I achieve this in F#?

Here is my code, which compiles with a warning:

let sha = new SHA1CryptoServiceProvider()
let maxLength = 10000
let fileSign file = 
    let fs = File.OpenRead(file)
    let mutable res = (0L, [|0uy|])
    try
        let flLen = fs.Length
        let len = int (min (int64 maxLength) flLen)

        // read 'len' bytes        
        let mutable pos = 0
        while (pos < len) do
            let chunk = fs.Read(buf, pos, len - pos)
            pos <- pos + chunk

        // get signature            
        let sign = sha.ComputeHash(buf, 0, len)

        // store new result
        res <- (flLen, sign)        
    with
        | :? IOException as e -> e |> ignore
    finally 
        if (fs <> null) then
            fs.Dispose()
    res

The warning is:
error FS0010: Unexpected keyword 'finally' in binding. Expected incomplete structured construct at or before this point or other token.

The corresponding C# equivalent for what I want is:

FileStream fs = null;
try
{
    fs = File.OpenRead(file);
    // ... other stuff
}
catch
{
    // I just do not specify anything
}
finally
{ 
    if (fs != null)
        fs.Dispose()
}

If I just omit the with block in F#, the exception is not ignored.

+4  A: 

try-with and try-finally are separate constructs in F#, so you need an extra 'try' to match the finally:

try
    try
        ...
    with e -> ...
finally
    ...

As Vitaliy points out, it's more idiomatic to use 'use' for finallys-that-dispose

use x = some-IDisposable-expr
...

See also

Docs about 'use': http://msdn.microsoft.com/en-us/library/dd233240%28VS.100%29.aspx

Spec for 'use': http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#%5FToc245030850

Brian
+3  A: 

try..with..finally is not supported in F#. As well as in OCaml. You should use use statement here:

try
   use fs = ...
with....
Vitaliy Liptchinsky