Thorsten Karrer
Thorsten Karrer

Reputation: 1365

Passing throwing functions as arguments

I am trying to simply pass a throwing function as an argument to another function, which will then cope with swift's error handling:

enum Err: ErrorType {
    case pfui
}

func bad(i: Int) throws -> String {
    if i < 10 {
        return String(i)
    } else {
        throw Err.pfui
    }
}

func handle(@autoclosure f: () throws -> String) -> String {
    do {
        return try f()
    }
    catch {
        return "oh snap"
    }
}


// error: call can throw but is not marked with 'try'
handle(bad(3))

It must be something simple that I am missing, but somehow the autoclosure attribute does not keep the compiler from thinking that I am actually calling it.

Upvotes: 5

Views: 3075

Answers (2)

Aaron Rasmussen
Aaron Rasmussen

Reputation: 13316

You can also use the rethrows keyword on handle to indicate that if the closure is a throwing function, handle will "re-throw" it. If you do that, then you don't need to catch the error inside of handle. So it depends on where you want to catch the error:

func handle(@autoclosure f: () throws -> String) rethrows -> String {
    return try f()
}

do { 
    try handle(bad(11))
} catch {
    print("\(error)")      // prints "pfui"
}

I guess it just depends on where you want to do your error handling. Do you want all errors handled inside of handle, or do you want to be able to handle them outside of handle?

Upvotes: 5

Thorsten Karrer
Thorsten Karrer

Reputation: 1365

Well... eventually found it out myself.

handle(try bad(3))

does the trick. In hindsight, the compiler was actually telling me what to do for a change. I still cannot figure out why I have to mark the name of a partially applied function with try at a place that is not the call site, however.

Upvotes: 2

Related Questions