2 people like it.

Deferred clean-up code (Go/Swift-style)

Go and Swift have a dedicated defer keyword which allows the programmer to specify code which should run when leaving the current scope, irrespective of errors. F# supports a similar pattern with IDisposable and the use keyword, but this requires either defining a class definition or object expression and the extra syntax can make the code less expressive. This snippet defines a simple helper function called "defer" to remedy the situation.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
let defer f = { new System.IDisposable with member __.Dispose() = f () }

let checkAnswer answerToEverything =
    use cleanup = defer (fun () ->
        // TODO: insert clean-up code here
        printfn "Did clean-up, leaving scope...")
    
    if answerToEverything = 42 then
        printfn "Well done!"
    else
        printfn "Oh, no!" 
        failwith "Catastrophic culture failure."

checkAnswer 42
checkAnswer 365
val defer : f:(unit -> unit) -> System.IDisposable

Full name: Script.defer
val f : (unit -> unit)
namespace System
type IDisposable =
  member Dispose : unit -> unit

Full name: System.IDisposable
val checkAnswer : answerToEverything:int -> unit

Full name: Script.checkAnswer
val answerToEverything : int
val cleanup : System.IDisposable
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
Raw view Test code New version

More information

Link:http://fssnip.net/rl
Posted:8 years ago
Author:Anton Tcholakov
Tags: dispose , defer , try/finally , exceptions