Defer in F#
Our example demonstrates the use of the use
keyword in F#, which is similar to the defer
concept in other languages. It ensures that a resource is properly disposed of when it goes out of scope.
open System
open System.IO
// Suppose we wanted to create a file, write to it,
// and then close when we're done. Here's how we could
// do that with `use`.
let main() =
// The `use` keyword ensures that the file is closed
// when it goes out of scope, similar to `defer` in other languages.
use f = createFile "/tmp/defer.txt"
writeFile f
and createFile (path: string) =
printfn "creating"
try
new StreamWriter(path)
with
| ex ->
failwithf "Failed to create file: %s" ex.Message
and writeFile (writer: StreamWriter) =
printfn "writing"
writer.WriteLine("data")
// It's important to handle exceptions when closing a file,
// even in a `use` block.
// The `use` keyword automatically calls Dispose on IDisposable objects,
// which includes closing for StreamWriter.
[<EntryPoint>]
let entryPoint _ =
main()
0
Running the program confirms that the file is created, written to, and then closed:
$ dotnet run
creating
writing
In F#, we use the use
keyword to ensure that disposable resources (like files) are properly cleaned up. This is similar to the defer
concept in other languages, but it’s more idiomatic to F# and .NET.
The use
keyword automatically calls the Dispose
method on the object when it goes out of scope, which for a StreamWriter
includes closing the file. This happens even if an exception is thrown, ensuring that resources are always properly cleaned up.
Note that in F#, we don’t need to explicitly close the file as we do in some other languages, because the use
keyword takes care of that for us. However, it’s still a good practice to handle any exceptions that might occur during file operations.