Your correct try ... with ... finally isn't supported, you can only have one or the other, I believe this is because it isn't supported in ocaml either. Personally I don't thinks its that useful to have both, as you correctly state the "use" binding ensures that any resouces that implement IDisposable are correctly clean up, and also "use" bindings are also most always better for cleaning up resources as scoping rules can make finally blocks difficult to use.

If you really need try ... with ... finally you can use a two nested trys:

1
2
3
4
5
6
7
8
9
let openFile(url: string) =
    let fileStream = System.IO.File.OpenText(url)
    try 
        try
          let readline = fileStream.ReadLine()
          printfn "Readline: %s" readline
        with ex -> printfn "Exception: %A" ex
    finally
        fileStream.Dispose()

Cheers,
Rob

By on 2/28/2008 12:17 AM ()

And if you need to improvise some kind of deterministic finalization (i.e. you're acquiring a resource, managed or unmanaged, that doesn't properly implement IDisposable), you can just wrap up the code you'd like to see in the finally block into an object expression. Note that this doesn't work correctly from the command line...

> use d =
- {
- new System.IDisposable
- with
- Dispose() =
- printfn "Hey!"
- };;

use d =
^

stdin(74,0): warning: 'use' bindings are treated as 'let' bindings in modules.

val d : IDisposable

> d.Dispose();;
Hey!
val it : unit = ()
>

By on 2/28/2008 5:58 AM ()

And if you need to improvise some kind of deterministic finalization (i.e. you're acquiring a resource, managed or unmanaged, that doesn't properly implement IDisposable), you can just wrap up the code you'd like to see in the finally block into an object expression.

That's a fantastic suggestion.

By on 2/29/2008 6:06 AM ()

And if you need to improvise some kind of deterministic finalization (i.e. you're acquiring a resource, managed or unmanaged, that doesn't properly implement IDisposable), you can just wrap up the code you'd like to see in the finally block into an object expression.

That's a fantastic suggestion.

You could take this a step further:

1
2
3
4
5
6
7
8
9
 

let disposable f = { new System.IDisposable
                       with Dispose() = f() }

let go =
  use d = disposable (fun () -> printfn "Finished")
  printfn "Start"
By on 2/29/2008 6:17 AM ()

And if you need to improvise some kind of deterministic finalization (i.e. you're acquiring a resource, managed or unmanaged, that doesn't properly implement IDisposable), you can just wrap up the code you'd like to see in the finally block into an object expression.

That's a fantastic suggestion.

You could take this a step further:

1
2
3
4
5
6
7
8
9
 

let disposable f = { new System.IDisposable
                       with Dispose() = f() }

let go =
  use d = disposable (fun () -> printfn "Finished")
  printfn "Start"

That is really fantastic idea.....thx...i m gonna use it very much...in future...

By on 3/10/2008 5:50 AM ()

i am sorry but i do not understand this example, i am hoping that someone would clue me in.
disposable type signature is

1
2
3
4
 

((unit -> unit) -> System.IDisposable)

wouldn't we want something that is:

1
2
 ('a -> (unit -> unit) -> 'a :> System.IDisposable)

seems like disposable is just generating something to dispose.

By on 11/17/2008 8:04 AM ()

Someone correct me if I'm wrong, as I'm still a little new to F# myself, but I believe the key point is that you can use local variables in your anonymous function. So, for example:

let disposable f = { new System.IDisposable
with Dispose() = f() }

let go =
let file = File.Open("SomeFile.txt")
use d = disposable (fun () -> file.Close())
printfn "Start"

In essence, this pattern allows you to specify an arbitrary "destructor" that can execute any sequence of code and manipulate any variables that are in scope at the time, that will always get called at the end of the use block. Exactly like the purpose of a finally statement, but you don't have to wrap it in a try / finally. In the C# world you're used to thinking about the concept of attaching Disposable to individual classes, but in this case you're creating an anonymous IDisposable object that stands alone, whose sole purpose is to allow you to execute arbitrary code on exit.

By on 11/17/2008 8:27 AM ()

Hi,
The "disposable" function here just "registeres" a function ("f") that will be called when the value we used during the registration is no longer in scope. Internally, this is done by the "use" keyword - when you declare a value using "use" it will be disposed once it is no longer in scope (which is just like "using" in C#).

In fact, you can do similar thing in C#:

1
2
3
4
5
6
7
8
9
class Disposable : IDisposable {
  Action f;
  public Disposable(Action f) { this.f = f; }
  public void Dispose() { f(); }
}

using(var d = new Disposable(()=> Console.WriteLine("end")) {
  // ..
}

The difference is that in C#, the scope is explicit, which makes the code (maybe) easier to understand, but less elegant.

However, this trick isn't really needed for freeing resources - it is interesting when you want to execute some user code at the end of the function. If you want to free resources (such as file stream) you can just use IDisposable and "use" keyword directly:

1
2
3
4
5
 
let go =
  use file = File.Open("SomeFile.txt")
  // do something with file
  printfn "Start"
By on 11/17/2008 8:41 AM ()

Dustin, that's exactly how I'm going to do it from now on. Nice!

By on 2/29/2008 7:29 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper