Do you need help on a specific subject? Use the contact form (Request a blog entry) on the right hand side.

2017-01-07

Cancelling a defer statement | Swift Pattern

I love the defer statement. It prevents so many error that could occur because one of the exits in a module may forget to close a file or release a resource etc.

I also do a fair amount of low-level programming and thus I get to write a lot of code that exits all over the place in case of an error, and has only one exit if everything went fine.

In order to use the defer statement, it need to release the resources on all the error exits, but not on the success exit.

So I would like to cancel a defer statement ... in a sense.

Of course that is not possible... is it?

No.

But there is a simple pattern that solves this problem neatly. It is so simple that it does not even need explaining:

func openFile(kind: String) -> UnsafeMutablePointer<FILE>? {
    
    var file = fopen("MyFile.txt", "r")
    
    var closeFile = true
    defer { if closeFile { fclose(file) } }
    
    if fileIsNotValid(file) { return nil }

    if fileDoesNotContainData(file, kind) { return nil }
    
    if fileDataOutOfDate(file) { return nil }
    
    // Prevent the deferred handler from closing the file
    closeFile = false

    return file
}

From Jay on the swift-evolution forum I received the following alternative:

func openFile(kind: String) -> UnsafeMutablePointer<FILE>? {
    
    var file = fopen("MyFile.txt", "r")
    
    var closeFile: (() -> Void)? = { fclose(file) }
    defer { closeFile?() }
    
    if fileIsNotValid(file) { return nil }

    if fileDoesNotContainsData(file, kind) { return nil }
    
    if fileDataOutOfDate(file) { return nil }
    
    // Prevent the deferred handler from closing the file
    closeFile = nil
    
    return file

}

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

No comments:

Post a Comment