Another way to do this is to write a function that takes all your throwing functions as an argument. It returns the first one that was successfully executed or nil.
func first<T>(_ values: (() throws -> T)...) -> T? {
return values.lazy.flatMap({ (throwingFunc) -> T? in
return try? throwingFunc()
}).first
}
The lazy ensures that the values are only called until it finds the first match. Doing it this way, you can also add a lot of cases very quickly.
You can use the function like this
return first(firstThing, secondThing, thirdThing) ?? "Default"
I also included the code I used to test this in playground:
enum ThingError: Error {
case zero
}
func firstThing() throws -> String {
print("0")
throw ThingError.zero
return "0"
}
func secondThing() throws -> String {
print("1")
return "1"
}
func thirdThing() throws -> String {
print("2")
return "B"
}
func first<T>(_ values: (() throws -> T)...) -> T? {
return values.lazy.flatMap({ (throwingFunc) -> T? in
return try? throwingFunc()
}).first
}
func tryThings() -> String {
return first(firstThing, secondThing, thirdThing) ?? "Default"
}
tryThings() // prints "0" and "1"