Nested do catch swift 3.0

I would like to use successive try attempts. If someone returns an error, I would like to move on to the next one, otherwise we will return the value. The code below seems to work fine, but in the end I get a lot of enclosed food to capture. Is there a smarter / better way to do this in Swift 3.0?

do { return try firstThing() } catch { do { return try secondThing() } catch { return try thirdThing() } } 
+5
source share
3 answers

If the actual errors caused by these function calls are not needed then can you use try? to convert the result to optional, and chain calls using the nil-coalescing operator ?? .

For instance:

 if let result = (try? firstThing()) ?? (try? secondThing()) ?? (try? thirdThing()) { return result } else { // everything failed ... } 

Or, if an error from the last method should be selected, if all fails, use try? for all but the last method call:

 return (try? firstThing()) ?? (try? secondThing()) ?? (try thirdThing()) 
+9
source

If Martin's answer is too short for your taste, you can just go with separate catch blocks.

 do { return try firstThing() } catch {} do { return try secondThing() } catch {} do { return try thirdThing() } catch {} return defaultThing() 

Since each result of the throw function returns immediately, nesting is not required.

+7
source

Another way to do this is to write a function that takes all your cast functions as an argument. It returns the first that was successful or zero.

 func first<T>(_ values: (() throws -> T)...) -> T? { return values.lazy.flatMap({ (throwingFunc) -> T? in return try? throwingFunc() }).first } 

lazy ensures that values ​​will only be called until it finds the first match. By doing this this way, you can also add a lot of things very quickly.

You can use a function like this

 return first(firstThing, secondThing, thirdThing) ?? "Default" 

I also included the code that I used to test on the 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" 
+3
source

Source: https://habr.com/ru/post/1270849/


All Articles